From 197abf8a20ee7a88707568cccf335bd94ea5df76 Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Tue, 18 Oct 2016 00:46:31 +0000 Subject: [PATCH 01/26] Initial progress --- .meteor/packages | 1 + .meteor/versions | 1 + .../.npm/package/.gitignore | 1 + .../rocketchat-irc-server/.npm/package/README | 7 + .../.npm/package/npm-shrinkwrap.json | 14 + packages/rocketchat-irc-server/Readme.md | 1 + packages/rocketchat-irc-server/package.js | 20 + .../server/irc-server.coffee | 790 ++++++++++++++++++ 8 files changed, 835 insertions(+) create mode 100644 packages/rocketchat-irc-server/.npm/package/.gitignore create mode 100644 packages/rocketchat-irc-server/.npm/package/README create mode 100644 packages/rocketchat-irc-server/.npm/package/npm-shrinkwrap.json create mode 100644 packages/rocketchat-irc-server/Readme.md create mode 100644 packages/rocketchat-irc-server/package.js create mode 100644 packages/rocketchat-irc-server/server/irc-server.coffee diff --git a/.meteor/packages b/.meteor/packages index dec57039741b5..e75356ff359bf 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -119,6 +119,7 @@ rocketchat:version rocketchat:videobridge rocketchat:webrtc rocketchat:wordpress +rocketchat:irc-server #rocketchat:bot-helpers #rocketchat:chatops #rocketchat:internal-hubot diff --git a/.meteor/versions b/.meteor/versions index bfab3ac697b2c..74030bc8db0d7 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -153,6 +153,7 @@ rocketchat:importer@0.0.1 rocketchat:importer-hipchat@0.0.1 rocketchat:importer-slack@0.0.1 rocketchat:integrations@0.0.1 +rocketchat:irc-server@0.0.1 rocketchat:katex@0.0.1 rocketchat:ldap@0.0.1 rocketchat:ldapjs@1.0.0 diff --git a/packages/rocketchat-irc-server/.npm/package/.gitignore b/packages/rocketchat-irc-server/.npm/package/.gitignore new file mode 100644 index 0000000000000..3c3629e647f5d --- /dev/null +++ b/packages/rocketchat-irc-server/.npm/package/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/packages/rocketchat-irc-server/.npm/package/README b/packages/rocketchat-irc-server/.npm/package/README new file mode 100644 index 0000000000000..3d492553a438e --- /dev/null +++ b/packages/rocketchat-irc-server/.npm/package/README @@ -0,0 +1,7 @@ +This directory and the files immediately inside it are automatically generated +when you change this package's NPM dependencies. Commit the files in this +directory (npm-shrinkwrap.json, .gitignore, and this README) to source control +so that others run the same versions of sub-dependencies. + +You should NOT check in the node_modules directory that Meteor automatically +creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/packages/rocketchat-irc-server/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-irc-server/.npm/package/npm-shrinkwrap.json new file mode 100644 index 0000000000000..bea157664c03e --- /dev/null +++ b/packages/rocketchat-irc-server/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,14 @@ +{ + "dependencies": { + "coffee-script": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.9.3.tgz", + "from": "coffee-script@1.9.3" + }, + "lru-cache": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", + "from": "lru-cache@2.6.5" + } + } +} diff --git a/packages/rocketchat-irc-server/Readme.md b/packages/rocketchat-irc-server/Readme.md new file mode 100644 index 0000000000000..5073cb244414d --- /dev/null +++ b/packages/rocketchat-irc-server/Readme.md @@ -0,0 +1 @@ +Move to [rocketchat-irc](https://github.com/haosdent/Rocket.Chat/tree/irc/packages/rocketchat-irc). \ No newline at end of file diff --git a/packages/rocketchat-irc-server/package.js b/packages/rocketchat-irc-server/package.js new file mode 100644 index 0000000000000..62902054c369c --- /dev/null +++ b/packages/rocketchat-irc-server/package.js @@ -0,0 +1,20 @@ +Package.describe({ + name: 'rocketchat:irc-server', + version: '0.0.1', + summary: 'RocketChat support for federating with IRC servers as a leaf node', + git: '' +}); + +Npm.depends({ + 'coffee-script': '1.9.3' +}); + +Package.onUse(function(api) { + api.use([ + 'coffeescript', + 'underscore', + 'rocketchat:lib' + ]); + + api.addFiles('server/irc-server.coffee', 'server'); +}); diff --git a/packages/rocketchat-irc-server/server/irc-server.coffee b/packages/rocketchat-irc-server/server/irc-server.coffee new file mode 100644 index 0000000000000..8faa334979f71 --- /dev/null +++ b/packages/rocketchat-irc-server/server/irc-server.coffee @@ -0,0 +1,790 @@ +net = Npm.require('net') + +MESSAGE_CACHE_SIZE = 200 +IRC_PORT = 6667 +IRC_HOST = 'irc.freenode.net' + +ircClientMap = {} + +bind = (f) -> + g = Meteor.bindEnvironment (self, args...) -> f.apply(self, args) + (args...) -> g @, args... + +async = (f, args...) -> + Meteor.wrapAsync(f)(args...) + +class IrcServer + constructor: () -> + @ircPort = 6666 + @ircHost = 'localhost' + @serverId = '777' + @sendPassword = 'password' + @receivePassword = 'password' + @serverName = 'rocket.chat' + @serverDescription = 'federated rocketchat server' + + @ircServers = {} + @ircUsers = {} + @localUsers = {} + @nextUid = parseInt('a00001', 36) + + @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 + + @partialMessage = '' + + @state = 'waitingforconnection' + + connect: () => + console.log "Connecting to IRC" + @socket.connect @ircPort, @ircHost, @onConnect + @state = 'connecting' + + disconnect: () => + @socket.end() + @state = 'waitingforconnection' + @cleanup() + + onConnect: () => + @writeCommand {command: 'PASS', parameters: [@sendPassword, 'TS', 6, @serverId]} + @writeCommand {command: 'CAPAB', trailer: 'TBURST EOB ENCAP'} + @writeCommand {command: 'SERVER', parameters: [@serverName, 1], trailer: @serverDescription} + #@socket.write "PASS #{@sendPassword} TS 6 #{@serverId}\r\n" + #@socket.write "CAPAB :TBURST EOB ENCAP\r\n" + #@socket.write "SERVER #{@serverName} 1 :#{@serverDescription}\r\n" + @state = 'awaitingpass' + + onClose: () => + @state = 'waitingforconnection' + @cleanup() + + cleanup: () => + @partialMessage = '' + @ircServers = {} + @ircUsers = {} + @localUsers = {} + + burst: () => + RocketChat.models.Users.find( {statusConnection: 'online'}, { fields: { _id: 1, username: 1, status: 1, name: 1}}).forEach @sendUser + RocketChat.models.Rooms.find( {}, {fields: { ts: 1, name: 1, usernames: 1, t: 1 } } ).forEach @sendRoom + + @writeCommand {command: 'EOB', prefix: @serverId} + + sendUser: (user) => + counterString = @nextUid.toString(36).toUpperCase() + @nextUid = @nextUid + 1 + data = {nickTimestamp: @getTime(), ircUserId: "#{@serverId}#{counterString}"} + @localUsers[user._id] = data + @writeCommand ( + prefix: @serverId + command: 'UID' + parameters: [user.username, 1, data.nickTimestamp, '+', user.username, @serverName, '127.0.0.1', data.ircUserId, '*'] + trailer: user.name + ) + + sendRoom: (room) => + if room.t == 'd' + return + + userIds = [] + RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { _id: 1, statusConnection: 1 } } ).forEach (user) => if user.statusConnection == 'online' then userIds.push(@localUsers[user._id].ircUserId) + + timestamp = Math.floor(room.ts.getTime()/1000) + nickSpace = 510 - 29 - room.name.length + nicksPerMessage = Math.floor(nickSpace / 20) + + index = 0 + while index * nicksPerMessage < userIds.length + @writeCommand + prefix: @serverId + command: 'SJOIN' + parameters: [timestamp, '#' + room.name, '+nt'] + trailer: userIds[index*nicksPerMessage...(index+1)*nicksPerMessage].join(' ') + index = index + 1 + + joinRoom: (user, room) => + if @state != 'connected' + return + + if room.t == 'd' or not user._id in @localUsers + return + + userId = @localUsers[user._id].ircUserId + timestamp = Math.floor(room.ts.getTime()/1000) + + @writeCommand + prefix: userId + command: 'JOIN' + parameters: [timestamp, '#' + room.name, '+'] + + loginUser: (user) => + if @state != 'connected' + return + + @sendUser user + RocketChat.models.Rooms.findByContainigUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } } ).forEach (room) => @joinRoom(user, room) + + leaveRoom: (user, room) => + if @state != 'connected' + return + + if room.t == 'd' or not user._id in @localUsers + return + + userId = @localUsers[user._id].ircUserId + @writeCommand + prefix: userId + command: 'PART' + parameters: ['#' + room.name] + + logoutUser: (user) => + if @state != 'connected' + return + + if not user._id in @localUsers + return + + userId = @localUsers[user._id].ircUserId + @writeCommand + prefix: userId + command: 'PART' + trailer: 'Signed out' + + sendMessage: (message, room) => + if @state != 'connected' + return + + if @localUsers[message.u._id] == undefined + return + + userId = @localUsers[message.u._id].ircUserId + + lines = message.msg.split('\n') + for line in lines + line = line.trimRight() + if room.t == 'd' + else + #TODO Should only send message if there are IRC users in the room + messageSpace = 510 - 22 - room.name.length + index = 0 + while index * messageSpace < line.length + @writeCommand + prefix: userId + command: 'PRIVMSG' + parameters: ['#' + room.name] + trailer: line.substring(index*messageSpace, (index+1)*messageSpace) + index = index + 1 + + loginIrcUser: (connectedTo, userId, nick, nickTimestamp, modes) => + #TODO Handle nick collisions + #TODO Handle verification that irc and rocketchat users are the same + #TODO Handle modes + user = Meteor.users.findOne {name: nick} + unless user + Meteor.call 'registerUser', + email: "#{nick}@redhat.com" + pass: '' + name: nick + user = Meteor.users.findOne {name: nick} + Meteor.users.update {_id: user._id}, + $set: + username: nick + ircOnly: true + Meteor.users.update {_id: user._id}, + $set: + status: 'online' + user.nickTimestamp = nickTimestamp + user.connectedTo = connectedTo + @ircUsers[userId] = user + console.log "Registered user #{nick} with userId #{userId}" + + logoutIrcUser: (userId) => + #TODO cleanup @ircUsers + user = @ircUsers[userId] + Meteor.users.update {_id: user._id}, + $set: + status: 'offline' + #TODO remove user from all rooms? + RocketChat.models.Rooms.removeUsernameFromAll(user.username) + + receiveIrcMessage: (userId, channel, message) => + user = @ircUsers[userId] + if channel[0] == '#' + room = RocketChat.models.Rooms.findOneByName channel.substring(1) + else + #TODO Handle direct messages + + message = + msg: message + ts: new Date() + RocketChat.sendMessage user, message, room + + + getTime: () => + Math.floor(Date.now()/1000) + + parseMessage: (message) => + result = {} + currentIndex = 0 + if message.length == 0 + return result + if message[0] == ':' + split = message.indexOf(' ', currentIndex) + result.prefix = if split == -1 + currentIndex = message.length + message.substring(1) + else + temp = message.substring(currentIndex+1, split) + currentIndex = split + 1 + temp + + if currentIndex != message.length + split = message.indexOf(' ', currentIndex) + result.command = if split == -1 + temp = message.substring(currentIndex) + currentIndex = message.length + temp + else + temp = message.substring(currentIndex, split) + currentIndex = split + 1 + temp + + result.parameters = while currentIndex != message.length and message[currentIndex] != ':' + split = message.indexOf(' ', currentIndex) + if split == -1 + temp = message.substring(currentIndex) + currentIndex = message.length + temp + else + temp = message.substring(currentIndex, split) + currentIndex = split + 1 + temp + + + if (currentIndex != message.length) + result.trailer = message.substring(currentIndex + 1) + + result + + writeCommand: (command) => + buffer = if command.prefix? then ":#{command.prefix} " else '' + buffer += command.command + if command.parameters? and command.parameters.length > 0 + buffer += ' ' + command.parameters.join(' ') + if command.trailer? + buffer += ' :' + command.trailer + + console.log "Sending Command: #{buffer}" + @socket.write(buffer + "\r\n") + + handleMalformed: (message) => + console.log "Received invalid message: #{message}" + + onReceiveRawMessage: (data) => + dataString = data.toString() + lines = dataString.split('\r\n') + + newPartialMessage = '' + if dataString.substr(dataString.length - 2) != "\n" + newPartialMessage = lines.pop() + + firstLine = true + + for line in lines + line = line.trim() + if firstLine + line = @partialMessage + line + firstLine = false + + console.log "Received message in state #{@state}: #{line}" + message = @parseMessage line + if not message.command? + continue + + switch @state + when 'awaitingpass' + if message.command == 'PASS' + if message.parameters.length != 4 + @handleMalformed(message) + @disconnect() + return + + [password, protocol, protocolVersion, @otherServerId] = message.parameters + if password != @receivePassword + @disconnect() + return + if protocol != 'TS' or protocolVersion != '6' + @disconnect() + return + + @ircServers[@otherServerId] = {proxiesServers: []} + @state = 'bursting' + when 'bursting' + switch message.command + when 'CAPAB' + @otherServerCapabilities = message.trailer.split(' ') + when 'SERVER' + if message.parameters.length != 2 or not message.trailer? + @handleMalformed(message) + @disconnect() + return + [serverName, hopCount] = message.parameters + if hopCount == '1' then @otherServerName = serverName + when 'SVINFO' + if message.parameters.length != 3 or not message.trailer? + @handleMalformed(message) + @disconnect() + return + [minTS, maxTS, discard] = message.parameters + timestamp = message.trailer + if minTS > 6 or maxTS < 6 + @disconnect() + return + + @writeCommand {prefix: @serverId, command: 'SVINFO', parameters: [6, 6, 0], trailer: @getTime()} + @burst() + when 'SID' + @onReceiveSID message + when 'SJOIN' + if message.parameters.length != 3 or not message.trailer? + @handleMalformed(message) + continue + [channelTimestamp, channel, mode] = message.parameters + userIds = message.trailer.split(' ') + room = RocketChat.models.Rooms.findOneByName channel.substring(1) + if not room? + continue #TODO Create missing channels? + usernames = _.map(userIds, (id) => @ircUsers[id].username) + RocketChat.models.Rooms.addUsernamesById(room._id, usernames) + when 'UID' + if message.parameters.length != 9 + @handleMalformed(message) + continue + [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, userId, gecos] = message.parameters + connectedTo = message.prefix + @loginIrcUser connectedTo, userId, nick, nickTimestamp, umodes + when 'PING' + source = message.trailer + @writeCommand {prefix: @serverId, command: 'PONG', parameters: [@serverName], trailer: source} + #@socket.write ":#{@serverId} PONG #{@serverName} :@{source}" + when 'EOB' + @state = 'connected' + when 'connected' + switch message.command + when 'PING' + source = message.trailer + @writeCommand {prefix: @serverId, command: 'PONG', parameters: [@serverName], trailer: source} + #@socket.write ":#{@serverId} PONG #{@serverName} :#{source}" + when 'UID' + if message.parameters.length != 9 + @handleMalformed(message) + continue + [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, userId, gecos] = message.parameters + connectedTo = message.prefix + @loginIrcUser connectedTo, userId, nick, nickTimestamp, umodes + when 'SID' + @onReceiveSID message + when 'SJOIN' + if message.parameters.length != 3 or not message.trailer? + @handleMalformed(message) + return + [channelTimestamp, channel, mode] = message.parameters + userIds = message.trailer.split(' ') + when 'SQUIT' + [targetServer] = message.parameters + comment = message.trailer + when 'JOIN' + userId = message.prefix + [channelTimestamp, channel, ...] = message.parameters + RocketChat.models.Rooms.addUsernameByName channel.substring(1), @ircUsers[userId].username + when 'PART' + userId = message.prefix + [channel] = message.parameters + RocketChat.models.Rooms.removeUsernameByName channel.substring(1), @ircUsers[userId].username + when 'QUIT' + userId = message.prefix + reason = message.trailer + @logoutIrcUser userId + when 'PRIVMSG' + userId = message.prefix + [channel] = message.parameters + content = message.trailer + @receiveIrcMessage userId, channel, content + + @partialMessage = newPartialMessage + + onReceiveSID: (command) => + if message.parameters.length != 3 or not message.trailer? or not message.prefix? + @handleMalformed(message) + return + + [serverName, hopCount, serverId] = message.parameters + connectedTo = message.prefix + serverDescription = message.trailer + + @ircServers[serverId] = {proxiesServers: []} + @ircServers[connectedTo].proxiesServers.push(serverId) + +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 + } + + +class IrcLoginer + constructor: (login) -> + if login.user? then ircServer.loginUser(login.user) + return login + + +class IrcSender + constructor: (message, room) -> + ircServer.sendMessage message, room + + +class IrcRoomJoiner + constructor: (user, room) -> + ircServer.joinRoom user, room + return room + + +class IrcRoomLeaver + constructor: (user, room) -> + ircServer.leaveRoom user, room + return room + + +class IrcLogoutCleanUper + constructor: (user) -> + ircServer.logoutUser user + return user + +RocketChat.callbacks.add 'afterValidateLogin', IrcLoginer, RocketChat.callbacks.priority.LOW, 'irc-loginer' +RocketChat.callbacks.add 'afterSaveMessage', IrcSender, RocketChat.callbacks.priority.LOW, 'irc-sender' +RocketChat.callbacks.add 'beforeJoinRoom', IrcRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-room-joiner' +RocketChat.callbacks.add 'beforeCreateChannel', IrcRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-room-joiner-create-channel' +RocketChat.callbacks.add 'beforeLeaveRoom', IrcRoomLeaver, RocketChat.callbacks.priority.LOW, 'irc-room-leaver' +RocketChat.callbacks.add 'afterLogoutCleanUp', IrcLogoutCleanUper, RocketChat.callbacks.priority.LOW, 'irc-clean-up' + +ircServer = new IrcServer +Meteor.startup -> + Meteor.setTimeout( (() => ircServer.connect()), 30000 ) + From 76c02b889711eb76a55a5cf68e4ac33614b20cd7 Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Tue, 18 Oct 2016 04:02:27 +0000 Subject: [PATCH 02/26] Direct messaging complete --- .../server/irc-server.coffee | 584 +++++++----------- 1 file changed, 239 insertions(+), 345 deletions(-) diff --git a/packages/rocketchat-irc-server/server/irc-server.coffee b/packages/rocketchat-irc-server/server/irc-server.coffee index 8faa334979f71..a62160888cc43 100644 --- a/packages/rocketchat-irc-server/server/irc-server.coffee +++ b/packages/rocketchat-irc-server/server/irc-server.coffee @@ -25,7 +25,8 @@ class IrcServer @ircServers = {} @ircUsers = {} - @localUsers = {} + @localUsersById = {} + @localUsersByIrcId = {} @nextUid = parseInt('a00001', 36) @socket = new net.Socket @@ -73,7 +74,8 @@ class IrcServer @partialMessage = '' @ircServers = {} @ircUsers = {} - @localUsers = {} + @localUsersById = {} + @localUsersByIrcId = {} burst: () => RocketChat.models.Users.find( {statusConnection: 'online'}, { fields: { _id: 1, username: 1, status: 1, name: 1}}).forEach @sendUser @@ -84,8 +86,9 @@ class IrcServer sendUser: (user) => counterString = @nextUid.toString(36).toUpperCase() @nextUid = @nextUid + 1 - data = {nickTimestamp: @getTime(), ircUserId: "#{@serverId}#{counterString}"} - @localUsers[user._id] = data + data = _.extend user, {nickTimestamp: @getTime(), ircUserId: "#{@serverId}#{counterString}"} + @localUsersById[data._id] = data + @localUsersByIrcId[data.ircUserId] = data @writeCommand ( prefix: @serverId command: 'UID' @@ -98,7 +101,8 @@ class IrcServer return userIds = [] - RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { _id: 1, statusConnection: 1 } } ).forEach (user) => if user.statusConnection == 'online' then userIds.push(@localUsers[user._id].ircUserId) + RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { _id: 1, statusConnection: 1 } } ).forEach (user) => + if user.statusConnection == 'online' then userIds.push(@localUsersById[user._id].ircUserId) timestamp = Math.floor(room.ts.getTime()/1000) nickSpace = 510 - 29 - room.name.length @@ -120,7 +124,7 @@ class IrcServer if room.t == 'd' or not user._id in @localUsers return - userId = @localUsers[user._id].ircUserId + userId = @localUsersById[user._id].ircUserId timestamp = Math.floor(room.ts.getTime()/1000) @writeCommand @@ -139,10 +143,10 @@ class IrcServer if @state != 'connected' return - if room.t == 'd' or not user._id in @localUsers + if room.t == 'd' or not user._id in @localUsersById return - userId = @localUsers[user._id].ircUserId + userId = @localUsersById[user._id].ircUserId @writeCommand prefix: userId command: 'PART' @@ -152,10 +156,12 @@ class IrcServer if @state != 'connected' return - if not user._id in @localUsers + if not user._id in @localUsersById return - userId = @localUsers[user._id].ircUserId + userId = @localUsersById[user._id].ircUserId + delete @localUsersById[user._id] + delete @localUsersByIrcId[userId] @writeCommand prefix: userId command: 'PART' @@ -165,49 +171,32 @@ class IrcServer if @state != 'connected' return - if @localUsers[message.u._id] == undefined + if @localUsersById[message.u._id] == undefined return - userId = @localUsers[message.u._id].ircUserId + userId = @localUsersById[message.u._id].ircUserId lines = message.msg.split('\n') for line in lines line = line.trimRight() if room.t == 'd' + messageSpace = 510 - 30 + targetUsername = _.find(room.usernames, (username) => username != message.u.username) + targetUser = _.find(@ircUsers, (user) => user.username == targetUsername) + target = targetUser.ircUserId else #TODO Should only send message if there are IRC users in the room messageSpace = 510 - 22 - room.name.length - index = 0 - while index * messageSpace < line.length - @writeCommand - prefix: userId - command: 'PRIVMSG' - parameters: ['#' + room.name] - trailer: line.substring(index*messageSpace, (index+1)*messageSpace) - index = index + 1 - - loginIrcUser: (connectedTo, userId, nick, nickTimestamp, modes) => - #TODO Handle nick collisions - #TODO Handle verification that irc and rocketchat users are the same - #TODO Handle modes - user = Meteor.users.findOne {name: nick} - unless user - Meteor.call 'registerUser', - email: "#{nick}@redhat.com" - pass: '' - name: nick - user = Meteor.users.findOne {name: nick} - Meteor.users.update {_id: user._id}, - $set: - username: nick - ircOnly: true - Meteor.users.update {_id: user._id}, - $set: - status: 'online' - user.nickTimestamp = nickTimestamp - user.connectedTo = connectedTo - @ircUsers[userId] = user - console.log "Registered user #{nick} with userId #{userId}" + target = '#' + room.name + + index = 0 + while index * messageSpace < line.length + @writeCommand + prefix: userId + command: 'PRIVMSG' + parameters: [target] + trailer: line.substring(index*messageSpace, (index+1)*messageSpace) + index = index + 1 logoutIrcUser: (userId) => #TODO cleanup @ircUsers @@ -215,65 +204,84 @@ class IrcServer Meteor.users.update {_id: user._id}, $set: status: 'offline' - #TODO remove user from all rooms? RocketChat.models.Rooms.removeUsernameFromAll(user.username) + delete @ircUsers[userId] - receiveIrcMessage: (userId, channel, message) => - user = @ircUsers[userId] - if channel[0] == '#' - room = RocketChat.models.Rooms.findOneByName channel.substring(1) - else - #TODO Handle direct messages - - message = - msg: message - ts: new Date() - RocketChat.sendMessage user, message, room + getDirectRoom: (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 + } getTime: () => Math.floor(Date.now()/1000) - parseMessage: (message) => + parseMessage: (command) => result = {} currentIndex = 0 - if message.length == 0 + if command.length == 0 return result - if message[0] == ':' - split = message.indexOf(' ', currentIndex) + if command[0] == ':' + split = command.indexOf(' ', currentIndex) result.prefix = if split == -1 - currentIndex = message.length - message.substring(1) + currentIndex = command.length + command.substring(1) else - temp = message.substring(currentIndex+1, split) + temp = command.substring(currentIndex+1, split) currentIndex = split + 1 temp - if currentIndex != message.length - split = message.indexOf(' ', currentIndex) + if currentIndex != command.length + split = command.indexOf(' ', currentIndex) result.command = if split == -1 - temp = message.substring(currentIndex) - currentIndex = message.length + temp = command.substring(currentIndex) + currentIndex = command.length temp else - temp = message.substring(currentIndex, split) + temp = command.substring(currentIndex, split) currentIndex = split + 1 temp - result.parameters = while currentIndex != message.length and message[currentIndex] != ':' - split = message.indexOf(' ', currentIndex) + result.parameters = while currentIndex != command.length and command[currentIndex] != ':' + split = command.indexOf(' ', currentIndex) if split == -1 - temp = message.substring(currentIndex) - currentIndex = message.length + temp = command.substring(currentIndex) + currentIndex = command.length temp else - temp = message.substring(currentIndex, split) + temp = command.substring(currentIndex, split) currentIndex = split + 1 temp - if (currentIndex != message.length) - result.trailer = message.substring(currentIndex + 1) + if (currentIndex != command.length) + result.trailer = command.substring(currentIndex + 1) result @@ -288,8 +296,8 @@ class IrcServer console.log "Sending Command: #{buffer}" @socket.write(buffer + "\r\n") - handleMalformed: (message) => - console.log "Received invalid message: #{message}" + handleMalformed: (command) => + console.log "Received invalid command: #{command}" onReceiveRawMessage: (data) => dataString = data.toString() @@ -307,324 +315,210 @@ class IrcServer line = @partialMessage + line firstLine = false - console.log "Received message in state #{@state}: #{line}" - message = @parseMessage line - if not message.command? + console.log "Received command in state #{@state}: #{line}" + command = @parseMessage line + if not command.command? continue switch @state when 'awaitingpass' - if message.command == 'PASS' - if message.parameters.length != 4 - @handleMalformed(message) - @disconnect() - return - - [password, protocol, protocolVersion, @otherServerId] = message.parameters - if password != @receivePassword - @disconnect() - return - if protocol != 'TS' or protocolVersion != '6' - @disconnect() - return - - @ircServers[@otherServerId] = {proxiesServers: []} - @state = 'bursting' + if command.command == 'PASS' + @onReceivePASS command when 'bursting' - switch message.command + switch command.command when 'CAPAB' - @otherServerCapabilities = message.trailer.split(' ') + @onReceiveCAPAB command when 'SERVER' - if message.parameters.length != 2 or not message.trailer? - @handleMalformed(message) - @disconnect() - return - [serverName, hopCount] = message.parameters - if hopCount == '1' then @otherServerName = serverName + @onReceiveSERVER command when 'SVINFO' - if message.parameters.length != 3 or not message.trailer? - @handleMalformed(message) - @disconnect() - return - [minTS, maxTS, discard] = message.parameters - timestamp = message.trailer - if minTS > 6 or maxTS < 6 - @disconnect() - return - - @writeCommand {prefix: @serverId, command: 'SVINFO', parameters: [6, 6, 0], trailer: @getTime()} - @burst() + @onReceiveSVINFO command when 'SID' - @onReceiveSID message + @onReceiveSID command when 'SJOIN' - if message.parameters.length != 3 or not message.trailer? - @handleMalformed(message) - continue - [channelTimestamp, channel, mode] = message.parameters - userIds = message.trailer.split(' ') - room = RocketChat.models.Rooms.findOneByName channel.substring(1) - if not room? - continue #TODO Create missing channels? - usernames = _.map(userIds, (id) => @ircUsers[id].username) - RocketChat.models.Rooms.addUsernamesById(room._id, usernames) + @onReceiveSJOIN command when 'UID' - if message.parameters.length != 9 - @handleMalformed(message) - continue - [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, userId, gecos] = message.parameters - connectedTo = message.prefix - @loginIrcUser connectedTo, userId, nick, nickTimestamp, umodes + @onReceiveUID command when 'PING' - source = message.trailer - @writeCommand {prefix: @serverId, command: 'PONG', parameters: [@serverName], trailer: source} - #@socket.write ":#{@serverId} PONG #{@serverName} :@{source}" + @onReceivePING command when 'EOB' - @state = 'connected' + @onReceiveEOB command when 'connected' - switch message.command + switch command.command when 'PING' - source = message.trailer - @writeCommand {prefix: @serverId, command: 'PONG', parameters: [@serverName], trailer: source} - #@socket.write ":#{@serverId} PONG #{@serverName} :#{source}" + @onReceivePING command when 'UID' - if message.parameters.length != 9 - @handleMalformed(message) - continue - [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, userId, gecos] = message.parameters - connectedTo = message.prefix - @loginIrcUser connectedTo, userId, nick, nickTimestamp, umodes + @onReceiveUID command when 'SID' - @onReceiveSID message + @onReceiveSID command when 'SJOIN' - if message.parameters.length != 3 or not message.trailer? - @handleMalformed(message) - return - [channelTimestamp, channel, mode] = message.parameters - userIds = message.trailer.split(' ') + @onReceiveSJOIN command when 'SQUIT' - [targetServer] = message.parameters - comment = message.trailer + @onReceiveSQUIT command when 'JOIN' - userId = message.prefix - [channelTimestamp, channel, ...] = message.parameters - RocketChat.models.Rooms.addUsernameByName channel.substring(1), @ircUsers[userId].username + @onReceiveJOIN command when 'PART' - userId = message.prefix - [channel] = message.parameters - RocketChat.models.Rooms.removeUsernameByName channel.substring(1), @ircUsers[userId].username + @onReceivePART command when 'QUIT' - userId = message.prefix - reason = message.trailer - @logoutIrcUser userId + @onReceiveQUIT command when 'PRIVMSG' - userId = message.prefix - [channel] = message.parameters - content = message.trailer - @receiveIrcMessage userId, channel, content + @onReceivePRIVMSG command @partialMessage = newPartialMessage - onReceiveSID: (command) => - if message.parameters.length != 3 or not message.trailer? or not message.prefix? - @handleMalformed(message) + onReceivePASS: (command) => + if command.parameters.length != 4 + @handleMalformed(command) + @disconnect() return - [serverName, hopCount, serverId] = message.parameters - connectedTo = message.prefix - serverDescription = message.trailer - - @ircServers[serverId] = {proxiesServers: []} - @ircServers[connectedTo].proxiesServers.push(serverId) - -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() + [password, protocol, protocolVersion, @otherServerId] = command.parameters + if password != @receivePassword + @disconnect() + return + if protocol != 'TS' or protocolVersion != '6' + @disconnect() + return - onTimeout: () => - console.log '[irc] onTimeout -> '.yellow, @user.username, 'connection timeout.', arguments + @ircServers[@otherServerId] = {proxiesServers: []} + @state = 'bursting' - onError: () => - console.log '[irc] onError -> '.yellow, @user.username, 'connection error.', arguments + onReceiveCAPAB: (command) => + @otherServerCapabilities = command.trailer.split(' ') - 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 + onReceiveSERVER: (command) => + if command.parameters.length != 2 or not command.trailer? + @handleMalformed(command) + @disconnect() + return + [serverName, hopCount] = command.parameters + @otherServerName = serverName - matchResult = @receiveMessageRegex.exec line - if matchResult - @onReceiveMessage matchResult[1], matchResult[2], matchResult[3] - continue + onReceiveSVINFO: (command) => + if command.parameters.length != 3 or not command.trailer? + @handleMalformed(command) + @disconnect() + return + [minTS, maxTS, discard] = command.parameters + timestamp = command.trailer + if minTS > 6 or maxTS < 6 + @disconnect() + return - matchResult = @receiveMemberListRegex.exec line - if matchResult - @onReceiveMemberList matchResult[1], matchResult[2].split ' ' - continue + @writeCommand {prefix: @serverId, command: 'SVINFO', parameters: [6, 6, 0], trailer: @getTime()} + @burst() + + onReceiveSID: (command) => + if command.parameters.length != 3 or not command.trailer? or not command.prefix? + @handleMalformed(command) + return - matchResult = @endMemberListRegex.exec line - if matchResult - @onEndMemberList matchResult[1] - continue + [serverName, hopCount, serverId] = command.parameters + connectedTo = command.prefix + serverDescription = command.trailer - matchResult = @addMemberToRoomRegex.exec line - if matchResult - @onAddMemberToRoom matchResult[1], matchResult[2] - continue + @ircServers[serverId] = {proxiesServers: []} + @ircServers[connectedTo].proxiesServers.push(serverId) - matchResult = @removeMemberFromRoomRegex.exec line - if matchResult - @onRemoveMemberFromRoom matchResult[1], matchResult[2] - continue + onReceiveSJOIN: (command) => + if command.parameters.length != 3 or not command.trailer? + @handleMalformed(command) + return - matchResult = @quiteMemberRegex.exec line - if matchResult - @onQuiteMember matchResult[1] - continue + [channelTimestamp, channel, mode] = command.parameters + userIds = command.trailer.split(' ') + room = RocketChat.models.Rooms.findOneByName channel.substring(1) + if not room? + return #TODO Create missing channels? + usernames = _.map(userIds, (id) => @ircUsers[id].username) + RocketChat.models.Rooms.addUsernamesById(room._id, usernames) + + onReceiveUID: (command) => + if command.parameters.length != 9 + @handleMalformed(command) + return + [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, userId, gecos] = command.parameters + connectedTo = command.prefix - matchResult = @successLoginMessageRegex.exec line - if matchResult - @onSuccessLoginMessage() - continue + #TODO Handle nick collisions + #TODO Handle verification that irc and rocketchat users are the same + #TODO Handle modes + user = Meteor.users.findOne {name: nick} + unless user + Meteor.call 'registerUser', + email: "#{nick}@irc.redhat.com" + pass: '' + name: nick + user = Meteor.users.findOne {name: nick} + Meteor.users.update {_id: user._id}, + $set: + username: nick + ircOnly: true + Meteor.users.update {_id: user._id}, + $set: + status: 'online' + user.nickTimestamp = nickTimestamp + user.connectedTo = connectedTo + user.ircUserId = userId + @ircUsers[userId] = user + console.log "Registered user #{nick} with userId #{userId}" - matchResult = @failedLoginMessageRegex.exec line - if matchResult - @onFailedLoginMessage() - continue + + + onReceivePING: (command) => + source = command.trailer + @writeCommand {prefix: @serverId, command: 'PONG', parameters: [@serverName], trailer: source} - 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 + onReceiveEOB: (command) => + @state = 'connected' + + onReceiveJOIN: (command) => + userId = command.prefix + [channelTimestamp, channel, ...] = command.parameters + RocketChat.models.Rooms.addUsernameByName channel.substring(1), @ircUsers[userId].username + + onReceivePART: (command) => + userId = command.prefix + [channel] = command.parameters + RocketChat.models.Rooms.removeUsernameByName channel.substring(1), @ircUsers[userId].username + + onReceiveQUIT: (command) => + userId = command.prefix + reason = command.trailer + @logoutIrcUser userId + + onReceiveSQUIT: (command) => + [targetServer] = command.parameters + comment = command.trailer + + onReceivePRIVMSG: (command) => + userId = command.prefix + [channel] = command.parameters + content = command.trailer - 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) + user = @ircUsers[userId] + if channel[0] == '#' + room = RocketChat.models.Rooms.findOneByName channel.substring(1) else - room = @createDirectRoomWhenNotExist(source, @user) + #TODO Handle direct messages + targetUser = @localUsersByIrcId[channel] + room = @getDirectRoom user, targetUser 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 + ts: new Date() + RocketChat.sendMessage user, message, room - for member in appendMembers - @createUserWhenNotExist member - RocketChat.models.Rooms.removeUsernamesById room._id, removeMembers - RocketChat.models.Rooms.addUsernamesById room._id, appendMembers +class IrcClient + constructor: (@loginReq) -> + @socket.on 'timeout', @onTimeout + @socket.on 'error', @onError - @isJoiningRoom = false - roomName = @pendingJoinRoomBuf.shift() - if roomName - @joinRoom - t: 'c' - name: roomName + onTimeout: () => + console.log '[irc] onTimeout -> '.yellow, @user.username, 'connection timeout.', arguments - sendRawMessage: (msg) -> - console.log '[irc] sendRawMessage -> '.yellow, msg.slice(0, -2) - if @isConnected - @socket.write msg - else - @msgBuf.push msg + onError: () => + console.log '[irc] onError -> '.yellow, @user.username, 'connection error.', arguments sendMessage: (room, message) -> console.log '[irc] sendMessage -> '.yellow, 'userName:', message.u.username From f6c433b38459457f45190ce48f3badf81e3ad6bf Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Tue, 18 Oct 2016 17:13:13 +0000 Subject: [PATCH 03/26] Handle net-splits --- .../server/irc-server.coffee | 151 +++--------------- 1 file changed, 22 insertions(+), 129 deletions(-) diff --git a/packages/rocketchat-irc-server/server/irc-server.coffee b/packages/rocketchat-irc-server/server/irc-server.coffee index a62160888cc43..923dae8e1dcbd 100644 --- a/packages/rocketchat-irc-server/server/irc-server.coffee +++ b/packages/rocketchat-irc-server/server/irc-server.coffee @@ -61,9 +61,6 @@ class IrcServer @writeCommand {command: 'PASS', parameters: [@sendPassword, 'TS', 6, @serverId]} @writeCommand {command: 'CAPAB', trailer: 'TBURST EOB ENCAP'} @writeCommand {command: 'SERVER', parameters: [@serverName, 1], trailer: @serverDescription} - #@socket.write "PASS #{@sendPassword} TS 6 #{@serverId}\r\n" - #@socket.write "CAPAB :TBURST EOB ENCAP\r\n" - #@socket.write "SERVER #{@serverName} 1 :#{@serverDescription}\r\n" @state = 'awaitingpass' onClose: () => @@ -72,8 +69,10 @@ class IrcServer cleanup: () => @partialMessage = '' - @ircServers = {} - @ircUsers = {} + + if @ircServers.length > 0 + @cleanupIrcServer @otherServerId + @localUsersById = {} @localUsersByIrcId = {} @@ -121,7 +120,7 @@ class IrcServer if @state != 'connected' return - if room.t == 'd' or not user._id in @localUsers + if room.t == 'd' or not user._id in @localUsersById return userId = @localUsersById[user._id].ircUserId @@ -199,7 +198,6 @@ class IrcServer index = index + 1 logoutIrcUser: (userId) => - #TODO cleanup @ircUsers user = @ircUsers[userId] Meteor.users.update {_id: user._id}, $set: @@ -207,6 +205,19 @@ class IrcServer RocketChat.models.Rooms.removeUsernameFromAll(user.username) delete @ircUsers[userId] + cleanupIrcServer: (serverId) => + disconnectedIds = [] + queue = [serverId] + + while queue.length > 0 + id = queue.pop() + disconnectedIds.push id + + queue = queue.concat @ircServers[id].proxiesServers + delete @ircServers[id] + + _.filter(@ircUsers, (user) => user.connectedTo in disconnectedIds).forEach @logoutIrcUser + getDirectRoom: (source, target) -> console.log '[irc] createDirectRoomWhenNotExist -> '.yellow, 'source:', source, 'target:', target rid = [source._id, target._id].sort().join('') @@ -490,6 +501,10 @@ class IrcServer [targetServer] = command.parameters comment = command.trailer + if targetServer == @serverId + targetServer = @otherServerId + @cleanupIrcServer targetServer + onReceivePRIVMSG: (command) => userId = command.prefix [channel] = command.parameters @@ -520,128 +535,6 @@ class IrcClient onError: () => console.log '[irc] onError -> '.yellow, @user.username, 'connection error.', arguments - 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 - } - class IrcLoginer constructor: (login) -> From 123f4e447b24b0d337de4f6dee0c18d9f0902976 Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Tue, 18 Oct 2016 20:15:52 +0000 Subject: [PATCH 04/26] Cleaned up logging --- .../server/irc-server.coffee | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/rocketchat-irc-server/server/irc-server.coffee b/packages/rocketchat-irc-server/server/irc-server.coffee index 923dae8e1dcbd..545ff5ae1e643 100644 --- a/packages/rocketchat-irc-server/server/irc-server.coffee +++ b/packages/rocketchat-irc-server/server/irc-server.coffee @@ -22,7 +22,9 @@ class IrcServer @receivePassword = 'password' @serverName = 'rocket.chat' @serverDescription = 'federated rocketchat server' - + + @logCommands = true + @ircServers = {} @ircUsers = {} @localUsersById = {} @@ -48,7 +50,7 @@ class IrcServer @state = 'waitingforconnection' connect: () => - console.log "Connecting to IRC" + console.log "Attempting connection to IRC on #{@ircHost}:#{@ircPort}" @socket.connect @ircPort, @ircHost, @onConnect @state = 'connecting' @@ -304,7 +306,8 @@ class IrcServer if command.trailer? buffer += ' :' + command.trailer - console.log "Sending Command: #{buffer}" + if @logCommands + console.log "Sending Command: #{buffer}" @socket.write(buffer + "\r\n") handleMalformed: (command) => @@ -326,7 +329,8 @@ class IrcServer line = @partialMessage + line firstLine = false - console.log "Received command in state #{@state}: #{line}" + if @logCommands + console.log "Received command: #{line}" command = @parseMessage line if not command.command? continue @@ -343,20 +347,18 @@ class IrcServer @onReceiveSERVER command when 'SVINFO' @onReceiveSVINFO command + when 'UID' + @onReceiveUID command when 'SID' @onReceiveSID command when 'SJOIN' @onReceiveSJOIN command - when 'UID' - @onReceiveUID command - when 'PING' - @onReceivePING command - when 'EOB' - @onReceiveEOB command when 'connected' switch command.command when 'PING' @onReceivePING command + when 'EOB' + @onReceiveEOB command when 'UID' @onReceiveUID command when 'SID' @@ -403,6 +405,7 @@ class IrcServer return [serverName, hopCount] = command.parameters @otherServerName = serverName + @ircServers[@otherServerId].serverName = serverName onReceiveSVINFO: (command) => if command.parameters.length != 3 or not command.trailer? @@ -415,8 +418,11 @@ class IrcServer @disconnect() return + console.log "Successfully connected to IRC server, starting to burst" @writeCommand {prefix: @serverId, command: 'SVINFO', parameters: [6, 6, 0], trailer: @getTime()} @burst() + console.log "Finished bursting" + @state = 'connected' onReceiveSID: (command) => if command.parameters.length != 3 or not command.trailer? or not command.prefix? @@ -427,9 +433,11 @@ class IrcServer connectedTo = command.prefix serverDescription = command.trailer - @ircServers[serverId] = {proxiesServers: []} + @ircServers[serverId] = {serverName: serverName, proxiesServers: []} @ircServers[connectedTo].proxiesServers.push(serverId) + console.log "New server connected: #{serverName} via #{@ircServers[connectedTo].serverName}" + onReceiveSJOIN: (command) => if command.parameters.length != 3 or not command.trailer? @handleMalformed(command) @@ -480,7 +488,8 @@ class IrcServer @writeCommand {prefix: @serverId, command: 'PONG', parameters: [@serverName], trailer: source} onReceiveEOB: (command) => - @state = 'connected' + serverId = command.prefix + console.log "Finished receiving burst from #{@ircServers[serverId].serverName}" onReceiveJOIN: (command) => userId = command.prefix @@ -503,6 +512,8 @@ class IrcServer if targetServer == @serverId targetServer = @otherServerId + + console.log "IRC server disconnecting: #{@ircServers[targetServer].serverName}" @cleanupIrcServer targetServer onReceivePRIVMSG: (command) => From 1e0045b5e4c8441e9007c9bc18d66e1785204083 Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Tue, 18 Oct 2016 21:04:56 +0000 Subject: [PATCH 05/26] more cleanup, better log messages --- .../server/irc-server.coffee | 113 +++++++++--------- 1 file changed, 56 insertions(+), 57 deletions(-) diff --git a/packages/rocketchat-irc-server/server/irc-server.coffee b/packages/rocketchat-irc-server/server/irc-server.coffee index 545ff5ae1e643..84759ec04af20 100644 --- a/packages/rocketchat-irc-server/server/irc-server.coffee +++ b/packages/rocketchat-irc-server/server/irc-server.coffee @@ -1,18 +1,9 @@ net = Npm.require('net') -MESSAGE_CACHE_SIZE = 200 -IRC_PORT = 6667 -IRC_HOST = 'irc.freenode.net' - -ircClientMap = {} - bind = (f) -> g = Meteor.bindEnvironment (self, args...) -> f.apply(self, args) (args...) -> g @, args... -async = (f, args...) -> - Meteor.wrapAsync(f)(args...) - class IrcServer constructor: () -> @ircPort = 6666 @@ -35,6 +26,7 @@ class IrcServer @socket.setNoDelay @socket.setEncoding 'utf-8' @socket.setKeepAlive true + @socket.setTimeout 90000 @onConnect = bind @onConnect @onClose = bind @onClose @onTimeout = bind @onTimeout @@ -50,7 +42,7 @@ class IrcServer @state = 'waitingforconnection' connect: () => - console.log "Attempting connection to IRC on #{@ircHost}:#{@ircPort}" + console.log "[irc-server] Attempting connection to IRC on #{@ircHost}:#{@ircPort}" @socket.connect @ircPort, @ircHost, @onConnect @state = 'connecting' @@ -66,9 +58,20 @@ class IrcServer @state = 'awaitingpass' onClose: () => + console.log "[irc-server] Socket closed, cleaning up state" @state = 'waitingforconnection' @cleanup() + onTimeout: () => + if @state == 'connected' or @state == 'bursting' + @writeCommand {command: 'PING', trailer: @otherServerId} + else + console.log "[irc-server] Timed out waiting for password" + @disconnect() + + onError: (error) => + console.log "[irc-server] Socket error: #{error.message}" + cleanup: () => @partialMessage = '' @@ -137,6 +140,9 @@ class IrcServer if @state != 'connected' return + if @localUsersById[user._id] != undefined + return + @sendUser user RocketChat.models.Rooms.findByContainigUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } } ).forEach (room) => @joinRoom(user, room) @@ -221,7 +227,6 @@ class IrcServer _.filter(@ircUsers, (user) => user.connectedTo in disconnectedIds).forEach @logoutIrcUser getDirectRoom: (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 @@ -307,11 +312,11 @@ class IrcServer buffer += ' :' + command.trailer if @logCommands - console.log "Sending Command: #{buffer}" + console.log "[irc-server] Sending Command: #{buffer}" @socket.write(buffer + "\r\n") handleMalformed: (command) => - console.log "Received invalid command: #{command}" + console.log "[irc-server] Received invalid command: #{command}" onReceiveRawMessage: (data) => dataString = data.toString() @@ -330,7 +335,7 @@ class IrcServer firstLine = false if @logCommands - console.log "Received command: #{line}" + console.log "[irc-server] Received command: #{line}" command = @parseMessage line if not command.command? continue @@ -353,10 +358,16 @@ class IrcServer @onReceiveSID command when 'SJOIN' @onReceiveSJOIN command + when 'PING' + @onReceivePING command + when 'PONG' + @onReceivePONG command when 'connected' switch command.command when 'PING' @onReceivePING command + when 'PONG' + @onReceivePONG command when 'EOB' @onReceiveEOB command when 'UID' @@ -418,10 +429,10 @@ class IrcServer @disconnect() return - console.log "Successfully connected to IRC server, starting to burst" + console.log "[irc-server] Successfully connected to IRC server, starting to burst" @writeCommand {prefix: @serverId, command: 'SVINFO', parameters: [6, 6, 0], trailer: @getTime()} @burst() - console.log "Finished bursting" + console.log "[irc-server] Finished bursting" @state = 'connected' onReceiveSID: (command) => @@ -436,7 +447,7 @@ class IrcServer @ircServers[serverId] = {serverName: serverName, proxiesServers: []} @ircServers[connectedTo].proxiesServers.push(serverId) - console.log "New server connected: #{serverName} via #{@ircServers[connectedTo].serverName}" + console.log "[irc-server] New server connected: #{serverName} via #{@ircServers[connectedTo].serverName}" onReceiveSJOIN: (command) => if command.parameters.length != 3 or not command.trailer? @@ -479,7 +490,7 @@ class IrcServer user.connectedTo = connectedTo user.ircUserId = userId @ircUsers[userId] = user - console.log "Registered user #{nick} with userId #{userId}" + console.log "[irc-server] Registered user #{nick} with userId #{userId}" @@ -487,9 +498,14 @@ class IrcServer source = command.trailer @writeCommand {prefix: @serverId, command: 'PONG', parameters: [@serverName], trailer: source} + onReceivePONG: (command) => + source = command.trailer + [sourceServerName] = command.parameters + targetServerId = command.trailer + onReceiveEOB: (command) => serverId = command.prefix - console.log "Finished receiving burst from #{@ircServers[serverId].serverName}" + console.log "[irc-server] Finished receiving burst from #{@ircServers[serverId].serverName}" onReceiveJOIN: (command) => userId = command.prefix @@ -513,7 +529,7 @@ class IrcServer if targetServer == @serverId targetServer = @otherServerId - console.log "IRC server disconnecting: #{@ircServers[targetServer].serverName}" + console.log "[irc-server] IRC server disconnecting: #{@ircServers[targetServer].serverName}" @cleanupIrcServer targetServer onReceivePRIVMSG: (command) => @@ -535,52 +551,35 @@ class IrcServer RocketChat.sendMessage user, message, room -class IrcClient - constructor: (@loginReq) -> - @socket.on 'timeout', @onTimeout - @socket.on 'error', @onError - - onTimeout: () => - console.log '[irc] onTimeout -> '.yellow, @user.username, 'connection timeout.', arguments - - onError: () => - console.log '[irc] onError -> '.yellow, @user.username, 'connection error.', arguments - - -class IrcLoginer - constructor: (login) -> - if login.user? then ircServer.loginUser(login.user) - return login +IrcServerLoginer = (login) -> + if login.user? then ircServer.loginUser(login.user) + return login -class IrcSender - constructor: (message, room) -> - ircServer.sendMessage message, room +IrcServerSender = (message, room) -> + ircServer.sendMessage message, room -class IrcRoomJoiner - constructor: (user, room) -> - ircServer.joinRoom user, room - return room +IrcServerRoomJoiner = (user, room) -> + ircServer.joinRoom user, room + return room -class IrcRoomLeaver - constructor: (user, room) -> - ircServer.leaveRoom user, room - return room +IrcServerRoomLeaver = (user, room) -> + ircServer.leaveRoom user, room + return room -class IrcLogoutCleanUper - constructor: (user) -> - ircServer.logoutUser user - return user +IrcServerLogoutCleanUper = (user) -> + ircServer.logoutUser user + return user -RocketChat.callbacks.add 'afterValidateLogin', IrcLoginer, RocketChat.callbacks.priority.LOW, 'irc-loginer' -RocketChat.callbacks.add 'afterSaveMessage', IrcSender, RocketChat.callbacks.priority.LOW, 'irc-sender' -RocketChat.callbacks.add 'beforeJoinRoom', IrcRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-room-joiner' -RocketChat.callbacks.add 'beforeCreateChannel', IrcRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-room-joiner-create-channel' -RocketChat.callbacks.add 'beforeLeaveRoom', IrcRoomLeaver, RocketChat.callbacks.priority.LOW, 'irc-room-leaver' -RocketChat.callbacks.add 'afterLogoutCleanUp', IrcLogoutCleanUper, RocketChat.callbacks.priority.LOW, 'irc-clean-up' +RocketChat.callbacks.add 'afterValidateLogin', IrcServerLoginer, RocketChat.callbacks.priority.LOW, 'irc-server-loginer' +RocketChat.callbacks.add 'afterSaveMessage', IrcServerSender, RocketChat.callbacks.priority.LOW, 'irc-server-sender' +RocketChat.callbacks.add 'beforeJoinRoom', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner' +RocketChat.callbacks.add 'beforeCreateChannel', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner-create-channel' +RocketChat.callbacks.add 'beforeLeaveRoom', IrcServerRoomLeaver, RocketChat.callbacks.priority.LOW, 'irc-server-room-leaver' +RocketChat.callbacks.add 'afterLogoutCleanUp', IrcServerLogoutCleanUper, RocketChat.callbacks.priority.LOW, 'irc-server-clean-up' ircServer = new IrcServer Meteor.startup -> From 39278a143c3c090fcc7784c24db57bcab13fb121 Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Thu, 20 Oct 2016 03:12:35 +0000 Subject: [PATCH 06/26] Added support for IRC users to create rooms and invite RC users --- .../server/irc-server.coffee | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/packages/rocketchat-irc-server/server/irc-server.coffee b/packages/rocketchat-irc-server/server/irc-server.coffee index 84759ec04af20..dc1541f7ec7ce 100644 --- a/packages/rocketchat-irc-server/server/irc-server.coffee +++ b/packages/rocketchat-irc-server/server/irc-server.coffee @@ -27,6 +27,7 @@ class IrcServer @socket.setEncoding 'utf-8' @socket.setKeepAlive true @socket.setTimeout 90000 + @onConnect = bind @onConnect @onClose = bind @onClose @onTimeout = bind @onTimeout @@ -64,7 +65,7 @@ class IrcServer onTimeout: () => if @state == 'connected' or @state == 'bursting' - @writeCommand {command: 'PING', trailer: @otherServerId} + @writeCommand {command: 'PING', trailer: @serverId} else console.log "[irc-server] Timed out waiting for password" @disconnect() @@ -125,7 +126,7 @@ class IrcServer if @state != 'connected' return - if room.t == 'd' or not user._id in @localUsersById + if room.t == 'd' or @localUsersById[user._id] == undefined return userId = @localUsersById[user._id].ircUserId @@ -333,7 +334,6 @@ class IrcServer if firstLine line = @partialMessage + line firstLine = false - if @logCommands console.log "[irc-server] Received command: #{line}" command = @parseMessage line @@ -362,6 +362,8 @@ class IrcServer @onReceivePING command when 'PONG' @onReceivePONG command + when 'INVITE' + @onReceiveINVITE command when 'connected' switch command.command when 'PING' @@ -384,6 +386,8 @@ class IrcServer @onReceivePART command when 'QUIT' @onReceiveQUIT command + when 'INVITE' + @onReceiveINVITE command when 'PRIVMSG' @onReceivePRIVMSG command @@ -456,11 +460,22 @@ class IrcServer [channelTimestamp, channel, mode] = command.parameters userIds = command.trailer.split(' ') + users = _.map(userIds, (id) => + { + username: @ircUsers[id.substring(id.length-9)].username, + isOperator: id[0] == '@' + } + + ) room = RocketChat.models.Rooms.findOneByName channel.substring(1) if not room? - return #TODO Create missing channels? - usernames = _.map(userIds, (id) => @ircUsers[id].username) - RocketChat.models.Rooms.addUsernamesById(room._id, usernames) + firstOperator = _.find(users, (user) => user.isOperator) + if not firstOperator? + return + RocketChat.createRoom('c', channel.substring(1), firstOperator.username, [], false) + room = RocketChat.models.Rooms.findOneByName channel.substring(1) + + RocketChat.models.Rooms.addUsernamesById(room._id, _.map(users, (user) => user.username)) onReceiveUID: (command) => if command.parameters.length != 9 @@ -522,6 +537,30 @@ class IrcServer reason = command.trailer @logoutIrcUser userId + onReceiveINVITE: (command) => + invitingUserId = command.prefix + [invitedUserId, channel, channelTimestamp] = command.parameters + + + invitingUser = @ircUsers[invitingUserId] + if not invitingUser? + return + + invitedUser = @localUsersByIrcId[invitedUserId] + if not invitedUser? + return + + room = RocketChat.models.Rooms.findOneByName channel.substring(1) + if not room? + return + + console.log "[irc-server] Inviting #{invitedUser.username} to #{room.name}" + + Meteor.runAsUser invitingUser._id, => + Meteor.call 'addUserToRoom', + rid: room._id + username: invitedUser.username + onReceiveSQUIT: (command) => [targetServer] = command.parameters comment = command.trailer From 33bc0581ec0ceff067e1acd538f15d98d267e482 Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Thu, 20 Oct 2016 04:58:42 +0000 Subject: [PATCH 07/26] Keep rooms in sync --- .../rocketchat-irc-server/server/irc-server.coffee | 12 ++++++++++++ .../rocketchat-lib/server/functions/createRoom.js | 3 +++ 2 files changed, 15 insertions(+) diff --git a/packages/rocketchat-irc-server/server/irc-server.coffee b/packages/rocketchat-irc-server/server/irc-server.coffee index dc1541f7ec7ce..86758a01bf247 100644 --- a/packages/rocketchat-irc-server/server/irc-server.coffee +++ b/packages/rocketchat-irc-server/server/irc-server.coffee @@ -160,6 +160,14 @@ class IrcServer command: 'PART' parameters: ['#' + room.name] + createRoom: (owner, room) => + if room.t == 'd' or @localUsersById[owner._id] == undefined + return + + @sendRoom room + + + logoutUser: (user) => if @state != 'connected' return @@ -613,12 +621,16 @@ IrcServerLogoutCleanUper = (user) -> ircServer.logoutUser user return user +IrcServerRoomCreator = (owner, room) -> + ircServer.createRoom owner, room + RocketChat.callbacks.add 'afterValidateLogin', IrcServerLoginer, RocketChat.callbacks.priority.LOW, 'irc-server-loginer' RocketChat.callbacks.add 'afterSaveMessage', IrcServerSender, RocketChat.callbacks.priority.LOW, 'irc-server-sender' RocketChat.callbacks.add 'beforeJoinRoom', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner' RocketChat.callbacks.add 'beforeCreateChannel', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner-create-channel' RocketChat.callbacks.add 'beforeLeaveRoom', IrcServerRoomLeaver, RocketChat.callbacks.priority.LOW, 'irc-server-room-leaver' RocketChat.callbacks.add 'afterLogoutCleanUp', IrcServerLogoutCleanUper, RocketChat.callbacks.priority.LOW, 'irc-server-clean-up' +RocketChat.callbacks.add 'afterCreateRoom', IrcServerRoomCreator, RocketChat.callbacks.priority.LOW, 'irc-server-room-creator' ircServer = new IrcServer Meteor.startup -> diff --git a/packages/rocketchat-lib/server/functions/createRoom.js b/packages/rocketchat-lib/server/functions/createRoom.js index e2f325eda6ee2..6311988adaa0f 100644 --- a/packages/rocketchat-lib/server/functions/createRoom.js +++ b/packages/rocketchat-lib/server/functions/createRoom.js @@ -87,6 +87,9 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly) { RocketChat.callbacks.run('afterCreateChannel', owner, room); }); } + Meteor.defer(() => { + RocketChat.callbacks.run('afterCreateRoom', owner, room); + }); return { rid: room._id From 72b4b83df747582d0dbdaaf38ac8d495e1d15435 Mon Sep 17 00:00:00 2001 From: Chris Pitman Date: Thu, 20 Oct 2016 05:20:55 +0000 Subject: [PATCH 08/26] IRC user can kick RC user --- .../server/irc-server.coffee | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/rocketchat-irc-server/server/irc-server.coffee b/packages/rocketchat-irc-server/server/irc-server.coffee index 86758a01bf247..721b02d1a31a3 100644 --- a/packages/rocketchat-irc-server/server/irc-server.coffee +++ b/packages/rocketchat-irc-server/server/irc-server.coffee @@ -372,6 +372,8 @@ class IrcServer @onReceivePONG command when 'INVITE' @onReceiveINVITE command + when 'KICK' + @onReceiveKICK command when 'connected' switch command.command when 'PING' @@ -396,6 +398,8 @@ class IrcServer @onReceiveQUIT command when 'INVITE' @onReceiveINVITE command + when 'KICK' + @onReceiveKICK command when 'PRIVMSG' @onReceivePRIVMSG command @@ -569,6 +573,30 @@ class IrcServer rid: room._id username: invitedUser.username + onReceiveKICK: (command) => + kickingUserId = command.prefix + [channel, kickedUserId] = command.parameters + + + kickingUser = @ircUsers[kickingUserId] + if not kickingUser? + return + + kickedUser = @localUsersByIrcId[kickedUserId] + if not kickedUser? + return + + room = RocketChat.models.Rooms.findOneByName channel.substring(1) + if not room? + return + + console.log "[irc-server] Kicking #{kickedUser.username} from #{room.name}" + + Meteor.runAsUser kickingUser._id, => + Meteor.call 'removeUserFromRoom', + rid: room._id + username: kickedUser.username + onReceiveSQUIT: (command) => [targetServer] = command.parameters comment = command.trailer From 702969c970de25f83591dc9bf1396d458130df4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lindo=C3=A9lio=20L=C3=A1zaro?= Date: Fri, 22 Dec 2017 07:47:23 -0200 Subject: [PATCH 09/26] Working on transcription of coffescript to ecmascript code and fitting on the codebase. --- .../.npm/package/.gitignore | 1 - .../rocketchat-irc-server/.npm/package/README | 7 - .../.npm/package/npm-shrinkwrap.json | 10 - packages/rocketchat-irc-server/package.js | 8 +- .../server/irc-server.coffee | 665 ------------------ ...irc-server-transcript.js => irc-server.js} | 46 +- .../rocketchat-lib/server/models/Rooms.js | 4 + 7 files changed, 25 insertions(+), 716 deletions(-) delete mode 100644 packages/rocketchat-irc-server/.npm/package/.gitignore delete mode 100644 packages/rocketchat-irc-server/.npm/package/README delete mode 100644 packages/rocketchat-irc-server/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/rocketchat-irc-server/server/irc-server.coffee rename packages/rocketchat-irc-server/server/{irc-server-transcript.js => irc-server.js} (95%) diff --git a/packages/rocketchat-irc-server/.npm/package/.gitignore b/packages/rocketchat-irc-server/.npm/package/.gitignore deleted file mode 100644 index 3c3629e647f5d..0000000000000 --- a/packages/rocketchat-irc-server/.npm/package/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/packages/rocketchat-irc-server/.npm/package/README b/packages/rocketchat-irc-server/.npm/package/README deleted file mode 100644 index 3d492553a438e..0000000000000 --- a/packages/rocketchat-irc-server/.npm/package/README +++ /dev/null @@ -1,7 +0,0 @@ -This directory and the files immediately inside it are automatically generated -when you change this package's NPM dependencies. Commit the files in this -directory (npm-shrinkwrap.json, .gitignore, and this README) to source control -so that others run the same versions of sub-dependencies. - -You should NOT check in the node_modules directory that Meteor automatically -creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/packages/rocketchat-irc-server/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-irc-server/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 111a56ff3081f..0000000000000 --- a/packages/rocketchat-irc-server/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 1, - "dependencies": { - "coffee-script": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.9.3.tgz", - "integrity": "sha1-WW5ug/z8tnxZZKtw1ES+/wrASsc=" - } - } -} diff --git a/packages/rocketchat-irc-server/package.js b/packages/rocketchat-irc-server/package.js index 6040d379fb711..eb0d7b235ac61 100644 --- a/packages/rocketchat-irc-server/package.js +++ b/packages/rocketchat-irc-server/package.js @@ -5,18 +5,12 @@ Package.describe({ git: '' }); -Npm.depends({ - 'coffee-script': '1.9.3' -}); - Package.onUse(function(api) { api.use([ 'ecmascript', - 'coffeescript', 'underscore', 'rocketchat:lib' ]); - api.addFiles('server/irc-server.coffee', 'server'); - api.addFiles('server/irc-server-transcript.js', 'server'); + api.addFiles('server/irc-server.js', 'server'); }); diff --git a/packages/rocketchat-irc-server/server/irc-server.coffee b/packages/rocketchat-irc-server/server/irc-server.coffee deleted file mode 100644 index 68cadf54a46c5..0000000000000 --- a/packages/rocketchat-irc-server/server/irc-server.coffee +++ /dev/null @@ -1,665 +0,0 @@ -net = Npm.require('net') - -bind = (f) -> - g = Meteor.bindEnvironment (self, args...) -> f.apply(self, args) - (args...) -> g @, args... - -class IrcServer - constructor: () -> - @ircPort = 6666 - @ircHost = 'localhost' - @serverId = '777' - @sendPassword = 'password' - @receivePassword = 'password' - @serverName = 'rocket.chat' - @serverDescription = 'federated rocketchat server' - - @logCommands = true - - @ircServers = {} - @ircUsers = {} - @localUsersById = {} - @localUsersByIrcId = {} - @nextUid = parseInt('a00001', 36) - - @socket = new net.Socket - @socket.setNoDelay - @socket.setEncoding 'utf-8' - @socket.setKeepAlive true - @socket.setTimeout 90000 - - @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 - - @partialMessage = '' - - @state = 'waitingforconnection' - - connect: () => - console.log "[irc-server] Attempting connection to IRC on #{@ircHost}:#{@ircPort}" - @socket.connect @ircPort, @ircHost, @onConnect - @state = 'connecting' - - disconnect: () => - @socket.end() - @state = 'waitingforconnection' - @cleanup() - - onConnect: () => - @writeCommand {command: 'PASS', parameters: [@sendPassword, 'TS', 6, @serverId]} - @writeCommand {command: 'CAPAB', trailer: 'TBURST EOB ENCAP'} - @writeCommand {command: 'SERVER', parameters: [@serverName, 1], trailer: @serverDescription} - @state = 'awaitingpass' - - onClose: () => - console.log "[irc-server] Socket closed, cleaning up state" - @state = 'waitingforconnection' - @cleanup() - - onTimeout: () => - if @state == 'connected' or @state == 'bursting' - @writeCommand {command: 'PING', trailer: @serverId} - else - console.log "[irc-server] Timed out waiting for password" - @disconnect() - - onError: (error) => - console.log "[irc-server] Socket error: #{error.message}" - - cleanup: () => - @partialMessage = '' - - if @ircServers.length > 0 - @cleanupIrcServer @otherServerId - - @localUsersById = {} - @localUsersByIrcId = {} - - burst: () => - RocketChat.models.Users.find( {statusConnection: 'online'}, { fields: { _id: 1, username: 1, status: 1, name: 1}}).forEach @sendUser - RocketChat.models.Rooms.find( {}, {fields: { ts: 1, name: 1, usernames: 1, t: 1 } } ).forEach @sendRoom - - @writeCommand {command: 'EOB', prefix: @serverId} - - sendUser: (user) => - counterString = @nextUid.toString(36).toUpperCase() - @nextUid = @nextUid + 1 - data = _.extend user, {nickTimestamp: @getTime(), ircUserId: "#{@serverId}#{counterString}"} - @localUsersById[data._id] = data - @localUsersByIrcId[data.ircUserId] = data - @writeCommand - prefix: @serverId - command: 'UID' - parameters: [user.username, 1, data.nickTimestamp, '+', user.username, @serverName, '127.0.0.1', data.ircUserId, '*'] - trailer: user.name - - sendRoom: (room) => - if room.t == 'd' - return - - userIds = [] - RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { _id: 1, statusConnection: 1 } } ).forEach (user) => - if user.statusConnection == 'online' then userIds.push(@localUsersById[user._id].ircUserId) - - timestamp = Math.floor(room.ts.getTime()/1000) - nickSpace = 510 - 29 - room.name.length - nicksPerMessage = Math.floor(nickSpace / 20) - - index = 0 - while index * nicksPerMessage < userIds.length - @writeCommand - prefix: @serverId - command: 'SJOIN' - parameters: [timestamp, '#' + room.name, '+nt'] - trailer: userIds[index*nicksPerMessage...(index+1)*nicksPerMessage].join(' ') - index = index + 1 - - joinRoom: (user, room) => - if @state != 'connected' - return - - if room.t == 'd' or @localUsersById[user._id] == undefined - return - - userId = @localUsersById[user._id].ircUserId - timestamp = Math.floor(room.ts.getTime()/1000) - - @writeCommand - prefix: userId - command: 'JOIN' - parameters: [timestamp, '#' + room.name, '+'] - - loginUser: (user) => - if @state != 'connected' - return - - if @localUsersById[user._id] != undefined - return - - @sendUser user - RocketChat.models.Rooms.findByContainigUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } } ).forEach (room) => @joinRoom(user, room) - - leaveRoom: (user, room) => - if @state != 'connected' - return - - if room.t == 'd' or not user._id in @localUsersById - return - - userId = @localUsersById[user._id].ircUserId - @writeCommand - prefix: userId - command: 'PART' - parameters: ['#' + room.name] - - createRoom: (owner, room) => - if room.t == 'd' or @localUsersById[owner._id] == undefined - return - - @sendRoom room - - - - logoutUser: (user) => - if @state != 'connected' - return - - if not user._id in @localUsersById - return - - userId = @localUsersById[user._id].ircUserId - delete @localUsersById[user._id] - delete @localUsersByIrcId[userId] - @writeCommand - prefix: userId - command: 'PART' - trailer: 'Signed out' - - sendMessage: (message, room) => - if @state != 'connected' - return - - if @localUsersById[message.u._id] == undefined - return - - userId = @localUsersById[message.u._id].ircUserId - - lines = message.msg.split('\n') - for line in lines - line = line.trimRight() - if room.t == 'd' - messageSpace = 510 - 30 - targetUsername = _.find(room.usernames, (username) => username != message.u.username) - targetUser = _.find(@ircUsers, (user) => user.username == targetUsername) - target = targetUser.ircUserId - else - #TODO Should only send message if there are IRC users in the room - messageSpace = 510 - 22 - room.name.length - target = '#' + room.name - - index = 0 - while index * messageSpace < line.length - @writeCommand - prefix: userId - command: 'PRIVMSG' - parameters: [target] - trailer: line.substring(index*messageSpace, (index+1)*messageSpace) - index = index + 1 - - logoutIrcUser: (userId) => - user = @ircUsers[userId] - Meteor.users.update {_id: user._id}, - $set: - status: 'offline' - RocketChat.models.Rooms.removeUsernameFromAll(user.username) - delete @ircUsers[userId] - - cleanupIrcServer: (serverId) => - disconnectedIds = [] - queue = [serverId] - - while queue.length > 0 - id = queue.pop() - disconnectedIds.push id - - queue = queue.concat @ircServers[id].proxiesServers - delete @ircServers[id] - - _.filter(@ircUsers, (user) => user.connectedTo in disconnectedIds).forEach @logoutIrcUser - - getDirectRoom: (source, 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 - } - - getTime: () => - Math.floor(Date.now()/1000) - - parseMessage: (command) => - result = {} - currentIndex = 0 - if command.length == 0 - return result - if command[0] == ':' - split = command.indexOf(' ', currentIndex) - result.prefix = if split == -1 - currentIndex = command.length - command.substring(1) - else - temp = command.substring(currentIndex+1, split) - currentIndex = split + 1 - temp - - if currentIndex != command.length - split = command.indexOf(' ', currentIndex) - result.command = if split == -1 - temp = command.substring(currentIndex) - currentIndex = command.length - temp - else - temp = command.substring(currentIndex, split) - currentIndex = split + 1 - temp - - result.parameters = while currentIndex != command.length and command[currentIndex] != ':' - split = command.indexOf(' ', currentIndex) - if split == -1 - temp = command.substring(currentIndex) - currentIndex = command.length - temp - else - temp = command.substring(currentIndex, split) - currentIndex = split + 1 - temp - - - if (currentIndex != command.length) - result.trailer = command.substring(currentIndex + 1) - - result - - writeCommand: (command) => - buffer = if command.prefix? then ":#{command.prefix} " else '' - buffer += command.command - if command.parameters? and command.parameters.length > 0 - buffer += ' ' + command.parameters.join(' ') - if command.trailer? - buffer += ' :' + command.trailer - - if @logCommands - console.log "[irc-server] Sending Command: #{buffer}" - @socket.write(buffer + "\r\n") - - handleMalformed: (command) => - console.log "[irc-server] Received invalid command: #{command}" - - onReceiveRawMessage: (data) => - dataString = data.toString() - lines = dataString.split('\r\n') - - newPartialMessage = '' - if dataString.substr(dataString.length - 2) != "\n" - newPartialMessage = lines.pop() - - firstLine = true - - for line in lines - line = line.trim() - if firstLine - line = @partialMessage + line - firstLine = false - if @logCommands - console.log "[irc-server] Received command: #{line}" - command = @parseMessage line - if not command.command? - continue - - switch @state - when 'awaitingpass' - if command.command == 'PASS' - @onReceivePASS command - when 'bursting' - switch command.command - when 'CAPAB' - @onReceiveCAPAB command - when 'SERVER' - @onReceiveSERVER command - when 'SVINFO' - @onReceiveSVINFO command - when 'UID' - @onReceiveUID command - when 'SID' - @onReceiveSID command - when 'SJOIN' - @onReceiveSJOIN command - when 'PING' - @onReceivePING command - when 'PONG' - @onReceivePONG command - when 'INVITE' - @onReceiveINVITE command - when 'KICK' - @onReceiveKICK command - when 'connected' - switch command.command - when 'PING' - @onReceivePING command - when 'PONG' - @onReceivePONG command - when 'EOB' - @onReceiveEOB command - when 'UID' - @onReceiveUID command - when 'SID' - @onReceiveSID command - when 'SJOIN' - @onReceiveSJOIN command - when 'SQUIT' - @onReceiveSQUIT command - when 'JOIN' - @onReceiveJOIN command - when 'PART' - @onReceivePART command - when 'QUIT' - @onReceiveQUIT command - when 'INVITE' - @onReceiveINVITE command - when 'KICK' - @onReceiveKICK command - when 'PRIVMSG' - @onReceivePRIVMSG command - - @partialMessage = newPartialMessage - - onReceivePASS: (command) => - if command.parameters.length != 4 - @handleMalformed(command) - @disconnect() - return - - [password, protocol, protocolVersion, @otherServerId] = command.parameters - if password != @receivePassword - @disconnect() - return - if protocol != 'TS' or protocolVersion != '6' - @disconnect() - return - - @ircServers[@otherServerId] = {proxiesServers: []} - @state = 'bursting' - - onReceiveCAPAB: (command) => - @otherServerCapabilities = command.trailer.split(' ') - - onReceiveSERVER: (command) => - if command.parameters.length != 2 or not command.trailer? - @handleMalformed(command) - @disconnect() - return - [serverName, hopCount] = command.parameters - @otherServerName = serverName - @ircServers[@otherServerId].serverName = serverName - - onReceiveSVINFO: (command) => - if command.parameters.length != 3 or not command.trailer? - @handleMalformed(command) - @disconnect() - return - [minTS, maxTS, discard] = command.parameters - timestamp = command.trailer - if minTS > 6 or maxTS < 6 - @disconnect() - return - - console.log "[irc-server] Successfully connected to IRC server, starting to burst" - @writeCommand {prefix: @serverId, command: 'SVINFO', parameters: [6, 6, 0], trailer: @getTime()} - @burst() - console.log "[irc-server] Finished bursting" - @state = 'connected' - - onReceiveSID: (command) => - if command.parameters.length != 3 or not command.trailer? or not command.prefix? - @handleMalformed(command) - return - - [serverName, hopCount, serverId] = command.parameters - connectedTo = command.prefix - serverDescription = command.trailer - - @ircServers[serverId] = {serverName: serverName, proxiesServers: []} - @ircServers[connectedTo].proxiesServers.push(serverId) - - console.log "[irc-server] New server connected: #{serverName} via #{@ircServers[connectedTo].serverName}" - - onReceiveSJOIN: (command) => - if command.parameters.length != 3 or not command.trailer? - @handleMalformed(command) - return - - [channelTimestamp, channel, mode] = command.parameters - userIds = command.trailer.split(' ') - users = _.map(userIds, (id) => - { - username: @ircUsers[id.substring(id.length-9)].username, - isOperator: id[0] == '@' - } - - ) - room = RocketChat.models.Rooms.findOneByName channel.substring(1) - if not room? - firstOperator = _.find(users, (user) => user.isOperator) - if not firstOperator? - return - RocketChat.createRoom('c', channel.substring(1), firstOperator.username, [], false) - room = RocketChat.models.Rooms.findOneByName channel.substring(1) - - RocketChat.models.Rooms.addUsernamesById(room._id, _.map(users, (user) => user.username)) - - onReceiveUID: (command) => - if command.parameters.length != 9 - @handleMalformed(command) - return - [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, userId, gecos] = command.parameters - connectedTo = command.prefix - - #TODO Handle nick collisions - #TODO Handle verification that irc and rocketchat users are the same - #TODO Handle modes - user = Meteor.users.findOne {name: nick} - unless user - Meteor.call 'registerUser', - email: "#{nick}@irc.redhat.com" - pass: '' - name: nick - user = Meteor.users.findOne {name: nick} - Meteor.users.update {_id: user._id}, - $set: - username: nick - ircOnly: true - Meteor.users.update {_id: user._id}, - $set: - status: 'online' - user.nickTimestamp = nickTimestamp - user.connectedTo = connectedTo - user.ircUserId = userId - @ircUsers[userId] = user - console.log "[irc-server] Registered user #{nick} with userId #{userId}" - - - - onReceivePING: (command) => - source = command.trailer - @writeCommand {prefix: @serverId, command: 'PONG', parameters: [@serverName], trailer: source} - - onReceivePONG: (command) => - source = command.trailer - [sourceServerName] = command.parameters - targetServerId = command.trailer - - onReceiveEOB: (command) => - serverId = command.prefix - console.log "[irc-server] Finished receiving burst from #{@ircServers[serverId].serverName}" - - onReceiveJOIN: (command) => - userId = command.prefix - [channelTimestamp, channel, ...] = command.parameters - RocketChat.models.Rooms.addUsernameByName channel.substring(1), @ircUsers[userId].username - - onReceivePART: (command) => - userId = command.prefix - [channel] = command.parameters - RocketChat.models.Rooms.removeUsernameByName channel.substring(1), @ircUsers[userId].username - - onReceiveQUIT: (command) => - userId = command.prefix - reason = command.trailer - @logoutIrcUser userId - - onReceiveINVITE: (command) => - invitingUserId = command.prefix - [invitedUserId, channel, channelTimestamp] = command.parameters - - - invitingUser = @ircUsers[invitingUserId] - if not invitingUser? - return - - invitedUser = @localUsersByIrcId[invitedUserId] - if not invitedUser? - return - - room = RocketChat.models.Rooms.findOneByName channel.substring(1) - if not room? - return - - console.log "[irc-server] Inviting #{invitedUser.username} to #{room.name}" - - Meteor.runAsUser invitingUser._id, => - Meteor.call 'addUserToRoom', - rid: room._id - username: invitedUser.username - - onReceiveKICK: (command) => - kickingUserId = command.prefix - [channel, kickedUserId] = command.parameters - - - kickingUser = @ircUsers[kickingUserId] - if not kickingUser? - return - - kickedUser = @localUsersByIrcId[kickedUserId] - if not kickedUser? - return - - room = RocketChat.models.Rooms.findOneByName channel.substring(1) - if not room? - return - - console.log "[irc-server] Kicking #{kickedUser.username} from #{room.name}" - - Meteor.runAsUser kickingUser._id, => - Meteor.call 'removeUserFromRoom', - rid: room._id - username: kickedUser.username - - onReceiveSQUIT: (command) => - [targetServer] = command.parameters - comment = command.trailer - - if targetServer == @serverId - targetServer = @otherServerId - - console.log "[irc-server] IRC server disconnecting: #{@ircServers[targetServer].serverName}" - @cleanupIrcServer targetServer - - onReceivePRIVMSG: (command) => - userId = command.prefix - [channel] = command.parameters - content = command.trailer - - user = @ircUsers[userId] - if channel[0] == '#' - room = RocketChat.models.Rooms.findOneByName channel.substring(1) - else - #TODO Handle direct messages - targetUser = @localUsersByIrcId[channel] - room = @getDirectRoom user, targetUser - - message = - msg: content - ts: new Date() - RocketChat.sendMessage user, message, room - - -IrcServerLoginer = (login) -> - if login.user? then ircServer.loginUser(login.user) - return login - - -IrcServerSender = (message, room) -> - ircServer.sendMessage message, room - - -IrcServerRoomJoiner = (user, room) -> - ircServer.joinRoom user, room - return room - - -IrcServerRoomLeaver = (user, room) -> - ircServer.leaveRoom user, room - return room - - -IrcServerLogoutCleanUper = (user) -> - ircServer.logoutUser user - return user - -IrcServerRoomCreator = (owner, room) -> - ircServer.createRoom owner, room - -RocketChat.callbacks.add 'afterValidateLogin', IrcServerLoginer, RocketChat.callbacks.priority.LOW, 'irc-server-loginer' -RocketChat.callbacks.add 'afterSaveMessage', IrcServerSender, RocketChat.callbacks.priority.LOW, 'irc-server-sender' -RocketChat.callbacks.add 'beforeJoinRoom', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner' -RocketChat.callbacks.add 'beforeCreateChannel', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner-create-channel' -RocketChat.callbacks.add 'beforeLeaveRoom', IrcServerRoomLeaver, RocketChat.callbacks.priority.LOW, 'irc-server-room-leaver' -RocketChat.callbacks.add 'afterLogoutCleanUp', IrcServerLogoutCleanUper, RocketChat.callbacks.priority.LOW, 'irc-server-clean-up' -RocketChat.callbacks.add 'afterCreateRoom', IrcServerRoomCreator, RocketChat.callbacks.priority.LOW, 'irc-server-room-creator' - -ircServer = new IrcServer -Meteor.startup -> - Meteor.setTimeout( (() => ircServer.connect()), 30000 ) - diff --git a/packages/rocketchat-irc-server/server/irc-server-transcript.js b/packages/rocketchat-irc-server/server/irc-server.js similarity index 95% rename from packages/rocketchat-irc-server/server/irc-server-transcript.js rename to packages/rocketchat-irc-server/server/irc-server.js index 32b78f479b3f3..2456ea81eddf1 100644 --- a/packages/rocketchat-irc-server/server/irc-server-transcript.js +++ b/packages/rocketchat-irc-server/server/irc-server.js @@ -50,13 +50,13 @@ class IrcServer { this.onReceivePRIVMSG = this.onReceivePRIVMSG.bind(this); // TODO: Make configurable by admin on settings - this.ircPort = 6666; - this.ircHost = 'localhost'; - this.serverId = '777'; + this.ircPort = 6667; + this.ircHost = 'chat.freenode.net'; + this.serverId = 'freenode'; this.sendPassword = 'password'; this.receivePassword = 'password'; this.serverName = 'rocket.chat'; - this.serverDescription = 'federated rocketchat server'; + this.serverDescription = 'Federated Rocket.Chat Server'; this.logCommands = true; @@ -67,7 +67,7 @@ class IrcServer { this.nextUid = parseInt('a00001', 36); this.socket = new net.Socket; - this.socket.setNoDelay; // TODO It's really necessary? + this.socket.setNoDelay(); this.socket.setEncoding('utf-8'); this.socket.setKeepAlive(true); this.socket.setTimeout(90000); @@ -249,8 +249,7 @@ class IrcServer { this.sendUser(user); - // TODO: Review this function on models... - return RocketChat.models.Rooms.findByContainigUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } }).forEach(room => this.joinRoom(user, room)); + return RocketChat.models.Rooms.findWithUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } }).forEach(room => this.joinRoom(user, room)); } leaveRoom(user, room) { @@ -258,8 +257,7 @@ class IrcServer { return; } - // TODO: Review this test expression - if (room.t === 'd' || this.localUsersById.includes(!user._id)) { + if (room.t === 'd' || !this.localUsersById.includes(user._id)) { return; } @@ -285,8 +283,7 @@ class IrcServer { return; } - // TODO: Review this test expression - if (this.localUsersById.includes(!user._id)) { + if (!this.localUsersById.includes(user._id)) { return; } @@ -379,7 +376,6 @@ class IrcServer { while (queue.length > 0) { const id = queue.pop(); - disconnectedIds.push(id); queue = queue.concat(this.ircServers[id].proxiesServers); @@ -474,7 +470,7 @@ class IrcServer { result.parameters = () => { const elementResult = []; - while ((currentIndex !== command.length) && (command[currentIndex] !== ':')) { + while (currentIndex !== command.length && command[currentIndex] !== ':') { split = command.indexOf(' ', currentIndex); if (split === -1) { @@ -499,10 +495,10 @@ class IrcServer { } writeCommand(command) { - let buffer = (command.prefix != null) ? `:${ command.prefix } ` : ''; + let buffer = command.prefix != null ? `:${ command.prefix } ` : ''; buffer += command.command; - if ((command.parameters != null) && (command.parameters.length > 0)) { + if (command.parameters != null && command.parameters.length > 0) { buffer += ` ${ command.parameters.join(' ') }`; } @@ -661,9 +657,10 @@ class IrcServer { return this.state = 'bursting'; } + // eslint-disable-next-line no-unused-vars onReceiveCAPAB(command) { // TODO: Review it - return this.otherServerCapabilities = command.trailer.split(' '); + // return this.otherServerCapabilities = command.trailer.split(' '); } onReceiveSERVER(command) { @@ -714,7 +711,6 @@ class IrcServer { } onReceiveSID(command) { - // TODO Transform to Meteor check... if (!command.parameters || command.parameters.length !== 3 || command.trailer == null || command.prefix == null) { this.handleMalformed(command); return; @@ -730,12 +726,10 @@ class IrcServer { this.ircServers[serverId] = {serverName, proxiesServers: []}; this.ircServers[connectedTo].proxiesServers.push(serverId); - // TODO It's right? Return log console? return console.log(`[irc-server] New server connected: ${ serverName } via ${ this.ircServers[connectedTo].serverName }`); } onReceiveSJOIN(command) { - // TODO Transform to Meteor check... if (command.parameters.length !== 3 || command.trailer == null) { this.handleMalformed(command); return; @@ -758,7 +752,7 @@ class IrcServer { if ((room == null)) { const firstOperator = _.find(users, user => user.isOperator); - if ((firstOperator == null)) { + if (firstOperator == null) { return; } @@ -871,17 +865,17 @@ class IrcServer { const [invitedUserId, channel, channelTimestamp] = command.parameters; const invitingUser = this.ircUsers[invitingUserId]; - if ((invitingUser == null)) { + if (invitingUser == null) { return; } const invitedUser = this.localUsersByIrcId[invitedUserId]; - if ((invitedUser == null)) { + if (invitedUser == null) { return; } const room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - if ((room == null)) { + if (room == null) { return; } @@ -900,17 +894,17 @@ class IrcServer { const [channel, kickedUserId] = command.parameters; const kickingUser = this.ircUsers[kickingUserId]; - if ((kickingUser == null)) { + if (kickingUser == null) { return; } const kickedUser = this.localUsersByIrcId[kickedUserId]; - if ((kickedUser == null)) { + if (kickedUser == null) { return; } const room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - if ((room == null)) { + if (room == null) { return; } diff --git a/packages/rocketchat-lib/server/models/Rooms.js b/packages/rocketchat-lib/server/models/Rooms.js index 31b5a28c136c8..e324ce31a7825 100644 --- a/packages/rocketchat-lib/server/models/Rooms.js +++ b/packages/rocketchat-lib/server/models/Rooms.js @@ -88,6 +88,10 @@ class ModelRooms extends RocketChat.models._Base { // FIND + findWithUsername(username, options) { + return this.find({ usernames: username }, options); + } + findById(roomId, options) { return this.find({ _id: roomId }, options); } From 6fc0d2a85d44e31debb96992a6ee752e2b326a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lindo=C3=A9lio=20L=C3=A1zaro?= Date: Fri, 22 Dec 2017 08:55:13 -0200 Subject: [PATCH 10/26] Adds settings section for config the IRC Server bridge. --- packages/rocketchat-irc-server/package.js | 3 +- .../{irc-server.js => irc-server-bridge.js} | 75 ++++++++++--------- .../server/irc-server-settings.js | 52 +++++++++++++ 3 files changed, 92 insertions(+), 38 deletions(-) rename packages/rocketchat-irc-server/server/{irc-server.js => irc-server-bridge.js} (91%) create mode 100644 packages/rocketchat-irc-server/server/irc-server-settings.js diff --git a/packages/rocketchat-irc-server/package.js b/packages/rocketchat-irc-server/package.js index eb0d7b235ac61..5b28aee5595f7 100644 --- a/packages/rocketchat-irc-server/package.js +++ b/packages/rocketchat-irc-server/package.js @@ -12,5 +12,6 @@ Package.onUse(function(api) { 'rocketchat:lib' ]); - api.addFiles('server/irc-server.js', 'server'); + api.addFiles('server/irc-server-bridge.js', 'server'); + api.addFiles('server/irc-server-settings.js', 'server'); }); diff --git a/packages/rocketchat-irc-server/server/irc-server.js b/packages/rocketchat-irc-server/server/irc-server-bridge.js similarity index 91% rename from packages/rocketchat-irc-server/server/irc-server.js rename to packages/rocketchat-irc-server/server/irc-server-bridge.js index 2456ea81eddf1..db644bc113490 100644 --- a/packages/rocketchat-irc-server/server/irc-server.js +++ b/packages/rocketchat-irc-server/server/irc-server-bridge.js @@ -49,14 +49,13 @@ class IrcServer { this.onReceiveSQUIT = this.onReceiveSQUIT.bind(this); this.onReceivePRIVMSG = this.onReceivePRIVMSG.bind(this); - // TODO: Make configurable by admin on settings - this.ircPort = 6667; - this.ircHost = 'chat.freenode.net'; - this.serverId = 'freenode'; - this.sendPassword = 'password'; - this.receivePassword = 'password'; - this.serverName = 'rocket.chat'; - this.serverDescription = 'Federated Rocket.Chat Server'; + this.ircPort = RocketChat.settings.get('IRC_Server_Port'); + this.ircHost = RocketChat.settings.get('IRC_Server_Host'); + this.serverId = RocketChat.settings.get('IRC_Server_Id'); + this.sendPassword = RocketChat.settings.get('IRC_Server_Send_Password'); + this.receivePassword = RocketChat.settings.get('IRC_Server_Receive_Password'); + this.serverName = RocketChat.settings.get('IRC_Server_Name'); + this.serverDescription = RocketChat.settings.get('IRC_Server_Description'); this.logCommands = true; @@ -957,40 +956,42 @@ class IrcServer { } } -const ircServer = new IrcServer; +if (!!RocketChat.settings.get('IRC_Server_Enabled') === true) { + const ircServer = new IrcServer; -const IrcServerLoginer = function(login) { - if (login.user != null) { ircServer.loginUser(login.user); } - return login; -}; + const IrcServerLoginer = function(login) { + if (login.user != null) { ircServer.loginUser(login.user); } + return login; + }; -const IrcServerSender = (message, room) => ircServer.sendMessage(message, room); + const IrcServerSender = (message, room) => ircServer.sendMessage(message, room); -const IrcServerRoomJoiner = function(user, room) { - ircServer.joinRoom(user, room); - return room; -}; + const IrcServerRoomJoiner = function(user, room) { + ircServer.joinRoom(user, room); + return room; + }; -const IrcServerRoomLeaver = function(user, room) { - ircServer.leaveRoom(user, room); - return room; -}; + const IrcServerRoomLeaver = function(user, room) { + ircServer.leaveRoom(user, room); + return room; + }; -const IrcServerLogoutCleanUper = function(user) { - ircServer.logoutUser(user); - return user; -}; + const IrcServerLogoutCleanUper = function(user) { + ircServer.logoutUser(user); + return user; + }; -const IrcServerRoomCreator = (owner, room) => ircServer.createRoom(owner, room); + const IrcServerRoomCreator = (owner, room) => ircServer.createRoom(owner, room); -RocketChat.callbacks.add('afterValidateLogin', IrcServerLoginer, RocketChat.callbacks.priority.LOW, 'irc-server-loginer'); -RocketChat.callbacks.add('afterSaveMessage', IrcServerSender, RocketChat.callbacks.priority.LOW, 'irc-server-sender'); -RocketChat.callbacks.add('beforeJoinRoom', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner'); -RocketChat.callbacks.add('beforeCreateChannel', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner-create-channel'); -RocketChat.callbacks.add('beforeLeaveRoom', IrcServerRoomLeaver, RocketChat.callbacks.priority.LOW, 'irc-server-room-leaver'); -RocketChat.callbacks.add('afterLogoutCleanUp', IrcServerLogoutCleanUper, RocketChat.callbacks.priority.LOW, 'irc-server-clean-up'); -RocketChat.callbacks.add('afterCreateRoom', IrcServerRoomCreator, RocketChat.callbacks.priority.LOW, 'irc-server-room-creator'); + RocketChat.callbacks.add('afterValidateLogin', IrcServerLoginer, RocketChat.callbacks.priority.LOW, 'irc-server-loginer'); + RocketChat.callbacks.add('afterSaveMessage', IrcServerSender, RocketChat.callbacks.priority.LOW, 'irc-server-sender'); + RocketChat.callbacks.add('beforeJoinRoom', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner'); + RocketChat.callbacks.add('beforeCreateChannel', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner-create-channel'); + RocketChat.callbacks.add('beforeLeaveRoom', IrcServerRoomLeaver, RocketChat.callbacks.priority.LOW, 'irc-server-room-leaver'); + RocketChat.callbacks.add('afterLogoutCleanUp', IrcServerLogoutCleanUper, RocketChat.callbacks.priority.LOW, 'irc-server-clean-up'); + RocketChat.callbacks.add('afterCreateRoom', IrcServerRoomCreator, RocketChat.callbacks.priority.LOW, 'irc-server-room-creator'); -Meteor.startup(() => { - Meteor.setTimeout((() => ircServer.connect()), 30000); -}); + Meteor.startup(() => { + Meteor.setTimeout((() => ircServer.connect()), 30000); + }); +} diff --git a/packages/rocketchat-irc-server/server/irc-server-settings.js b/packages/rocketchat-irc-server/server/irc-server-settings.js new file mode 100644 index 0000000000000..6398d953f373b --- /dev/null +++ b/packages/rocketchat-irc-server/server/irc-server-settings.js @@ -0,0 +1,52 @@ +Meteor.startup(function() { + RocketChat.settings.addGroup('IRC_Server', function() { + this.add('IRC_Server_Enabled', false, { + type: 'boolean', + i18nLabel: 'Enabled', + i18nDescription: 'IRC_Server_Enabled', + alert: 'IRC Server Support is a work in progress. Use on a production system is not recommended at this time.' + }); + + this.add('IRC_Server_Host', 'irc.freenode.net', { + type: 'string', + i18nLabel: 'Host', + i18nDescription: 'IRC_Server_Host' + }); + + this.add('IRC_Server_Port', 6667, { + type: 'int', + i18nLabel: 'Port', + i18nDescription: 'IRC_Server_Port' + }); + + this.add('IRC_Server_Id', null, { + type: 'string', + i18nLabel: 'Id', + i18nDescription: 'IRC_Server_Id' + }); + + this.add('IRC_Server_Send_Password', null, { + type: 'string', + i18nLabel: 'Send_Password', + i18nDescription: 'IRC_Server_Send_Password' + }); + + this.add('IRC_Server_Receive_Password', null, { + type: 'string', + i18nLabel: 'Receive_Password', + i18nDescription: 'IRC_Server_Receive_Password' + }); + + this.add('IRC_Server_Name', null, { + type: 'string', + i18nLabel: 'Name', + i18nDescription: 'IRC_Server_Name' + }); + + this.add('IRC_Server_Description', null, { + type: 'string', + i18nLabel: 'Description', + i18nDescription: 'IRC_Server_Description' + }); + }); +}); From f997ad212679cbb81203c2acaf3cfbed85044d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lindo=C3=A9lio=20L=C3=A1zaro?= Date: Mon, 29 Jan 2018 17:22:10 -0200 Subject: [PATCH 11/26] Working handles for direct messages --- .meteor/versions | 8 +- packages/rocketchat-irc-server/README.md | 9 + packages/rocketchat-irc-server/Readme.md | 1 - .../server/irc-server-bridge.js | 293 ++-- .../server/irc-server-settings.js | 13 +- .../.app/package-lock.json | 1538 +++++++++-------- 6 files changed, 1038 insertions(+), 824 deletions(-) create mode 100644 packages/rocketchat-irc-server/README.md delete mode 100644 packages/rocketchat-irc-server/Readme.md diff --git a/.meteor/versions b/.meteor/versions index 9032f80fb5077..cd5c5dece0677 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -112,6 +112,11 @@ ostrio:cookies@2.2.4 pauli:accounts-linkedin@2.1.3 pauli:linkedin-oauth@1.2.0 percolate:synced-cron@1.3.2 +practicalmeteor:chai@2.1.0_1 +practicalmeteor:loglevel@1.2.0_2 +practicalmeteor:mocha@2.4.5_6 +practicalmeteor:mocha-core@1.0.1 +practicalmeteor:sinon@1.14.1_2 promise@0.10.0 raix:eventemitter@0.1.3 raix:eventstate@0.0.4 @@ -165,8 +170,8 @@ rocketchat:importer-slack-users@1.0.0 rocketchat:integrations@0.0.1 rocketchat:internal-hubot@0.0.1 rocketchat:irc@0.0.2 -rocketchat:issuelinks@0.0.1 rocketchat:irc-server@0.0.1 +rocketchat:issuelinks@0.0.1 rocketchat:katex@0.0.1 rocketchat:ldap@0.0.1 rocketchat:lib@0.0.1 @@ -248,6 +253,7 @@ templating@1.3.2 templating-compiler@1.3.3 templating-runtime@1.3.2 templating-tools@1.1.2 +tmeasday:test-reporter-helpers@0.2.1 todda00:friendly-slugs@0.6.0 tracker@1.1.3 twitter-oauth@1.2.0 diff --git a/packages/rocketchat-irc-server/README.md b/packages/rocketchat-irc-server/README.md new file mode 100644 index 0000000000000..677fecd9c7c2a --- /dev/null +++ b/packages/rocketchat-irc-server/README.md @@ -0,0 +1,9 @@ +**IRC Server Federation** + +Provides an IRC Network environmet with Docker for tests. + +``` +docker run --name ircd -p 6667:6667 -p 7000:7000 inspircd/inspircd-docker +``` + +Add settings for your IRC Network on central admin at Rocket.Chat instance. diff --git a/packages/rocketchat-irc-server/Readme.md b/packages/rocketchat-irc-server/Readme.md deleted file mode 100644 index 5073cb244414d..0000000000000 --- a/packages/rocketchat-irc-server/Readme.md +++ /dev/null @@ -1 +0,0 @@ -Move to [rocketchat-irc](https://github.com/haosdent/Rocket.Chat/tree/irc/packages/rocketchat-irc). \ No newline at end of file diff --git a/packages/rocketchat-irc-server/server/irc-server-bridge.js b/packages/rocketchat-irc-server/server/irc-server-bridge.js index db644bc113490..4e70a69f2801d 100644 --- a/packages/rocketchat-irc-server/server/irc-server-bridge.js +++ b/packages/rocketchat-irc-server/server/irc-server-bridge.js @@ -1,53 +1,53 @@ import net from 'net'; import _ from 'underscore'; -const bind = function(f) { - const g = Meteor.bindEnvironment((self, ...args) => f.apply(self, args)); - return function(...args) { return g(this, ...Array.from(args)); }; -}; +// const bind = function(f) { +// const g = Meteor.bindEnvironment((self, ...args) => f.apply(self, args)); +// return function(...args) { return g(this, ...Array.from(args)); }; +// }; class IrcServer { constructor() { - this.connect = this.connect.bind(this); - this.disconnect = this.disconnect.bind(this); - this.onConnect = this.onConnect.bind(this); - this.onClose = this.onClose.bind(this); - this.onTimeout = this.onTimeout.bind(this); - this.onError = this.onError.bind(this); - this.cleanup = this.cleanup.bind(this); - this.burst = this.burst.bind(this); - this.sendUser = this.sendUser.bind(this); - this.sendRoom = this.sendRoom.bind(this); - this.joinRoom = this.joinRoom.bind(this); - this.loginUser = this.loginUser.bind(this); - this.leaveRoom = this.leaveRoom.bind(this); - this.createRoom = this.createRoom.bind(this); - this.logoutUser = this.logoutUser.bind(this); - this.sendMessage = this.sendMessage.bind(this); - this.logoutIrcUser = this.logoutIrcUser.bind(this); - this.cleanupIrcServer = this.cleanupIrcServer.bind(this); - this.getTime = this.getTime.bind(this); - this.parseMessage = this.parseMessage.bind(this); - this.writeCommand = this.writeCommand.bind(this); - this.handleMalformed = this.handleMalformed.bind(this); - this.onReceiveRawMessage = this.onReceiveRawMessage.bind(this); - this.onReceivePASS = this.onReceivePASS.bind(this); - this.onReceiveCAPAB = this.onReceiveCAPAB.bind(this); - this.onReceiveSERVER = this.onReceiveSERVER.bind(this); - this.onReceiveSVINFO = this.onReceiveSVINFO.bind(this); - this.onReceiveSID = this.onReceiveSID.bind(this); - this.onReceiveSJOIN = this.onReceiveSJOIN.bind(this); - this.onReceiveUID = this.onReceiveUID.bind(this); - this.onReceivePING = this.onReceivePING.bind(this); - this.onReceivePONG = this.onReceivePONG.bind(this); - this.onReceiveEOB = this.onReceiveEOB.bind(this); - this.onReceiveJOIN = this.onReceiveJOIN.bind(this); - this.onReceivePART = this.onReceivePART.bind(this); - this.onReceiveQUIT = this.onReceiveQUIT.bind(this); - this.onReceiveINVITE = this.onReceiveINVITE.bind(this); - this.onReceiveKICK = this.onReceiveKICK.bind(this); - this.onReceiveSQUIT = this.onReceiveSQUIT.bind(this); - this.onReceivePRIVMSG = this.onReceivePRIVMSG.bind(this); + // this.connect = bind(this.connect); + // this.disconnect = bind(this.disconnect); + // this.onConnect = bind(this.onConnect); + // this.onClose = bind(this.onClose); + // this.onTimeout = bind(this.onTimeout); + // this.onError = bind(this.onError); + // this.cleanup = bind(this.cleanup); + // this.burst = bind(this.burst); + // this.sendUser = bind(this.sendUser); + // this.sendRoom = bind(this.sendRoom); + // this.joinRoom = bind(this.joinRoom); + // this.loginUser = bind(this.loginUser); + // this.leaveRoom = bind(this.leaveRoom); + // this.createRoom = bind(this.createRoom); + // this.logoutUser = bind(this.logoutUser); + // this.sendMessage = bind(this.sendMessage); + // this.logoutIrcUser = bind(this.logoutIrcUser); + // this.cleanupIrcServer = bind(this.cleanupIrcServer); + // this.getTime = bind(this.getTime); + // this.parseMessage = bind(this.parseMessage); + // this.writeCommand = bind(this.writeCommand); + // this.handleMalformed = bind(this.handleMalformed); + // this.onReceiveRawMessage = bind(this.onReceiveRawMessage); + // this.onReceivePASS = bind(this.onReceivePASS); + // this.onReceiveCAPAB = bind(this.onReceiveCAPAB); + // this.onReceiveSERVER = bind(this.onReceiveSERVER); + // this.onReceiveSVINFO = bind(this.onReceiveSVINFO); + // this.onReceiveSID = bind(this.onReceiveSID); + // this.onReceiveSJOIN = bind(this.onReceiveSJOIN); + // this.onReceiveUID = bind(this.onReceiveUID); + // this.onReceivePING = bind(this.onReceivePING); + // this.onReceivePONG = bind(this.onReceivePONG); + // this.onReceiveEOB = bind(this.onReceiveEOB); + // this.onReceiveJOIN = bind(this.onReceiveJOIN); + // this.onReceivePART = bind(this.onReceivePART); + // this.onReceiveQUIT = bind(this.onReceiveQUIT); + // this.onReceiveINVITE = bind(this.onReceiveINVITE); + // this.onReceiveKICK = bind(this.onReceiveKICK); + // this.onReceiveSQUIT = bind(this.onReceiveSQUIT); + // this.onReceivePRIVMSG = bind(this.onReceivePRIVMSG); this.ircPort = RocketChat.settings.get('IRC_Server_Port'); this.ircHost = RocketChat.settings.get('IRC_Server_Host'); @@ -57,6 +57,17 @@ class IrcServer { this.serverName = RocketChat.settings.get('IRC_Server_Name'); this.serverDescription = RocketChat.settings.get('IRC_Server_Description'); + // TODO: Remove it... + console.log('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'); + console.log('>>> IRC host: ', this.ircHost); + console.log('>>> IRC port: ', this.ircPort); + console.log('>>> IRC serverId: ', this.serverId); + console.log('>>> IRC sendPassword: ', this.sendPassword); + console.log('>>> IRC receivePassword: ', this.receivePassword); + console.log('>>> IRC serverName: ', this.serverName); + console.log('>>> IRC serverDescription: ', this.serverDescription); + console.log('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'); + this.logCommands = true; this.ircServers = {}; @@ -71,12 +82,6 @@ class IrcServer { this.socket.setKeepAlive(true); this.socket.setTimeout(90000); - this.onConnect = bind(this.onConnect); - this.onClose = bind(this.onClose); - this.onTimeout = bind(this.onTimeout); - this.onError = bind(this.onError); - this.onReceiveRawMessage = bind(this.onReceiveRawMessage); - this.socket.on('data', this.onReceiveRawMessage); this.socket.on('close', this.onClose); this.socket.on('timeout', this.onTimeout); @@ -121,6 +126,7 @@ class IrcServer { onClose() { console.log('[irc-server] Socket closed, cleaning up state'); this.state = 'waitingforconnection'; + return this.cleanup(); } @@ -137,6 +143,7 @@ class IrcServer { } onError(error) { + console.log(error); return console.log(`[irc-server] Socket error: ${ error.message }`); } @@ -189,6 +196,7 @@ class IrcServer { } const userIds = []; + // TODO It probably should to be limited by statusConnection equals 'online' const subscribedUsers = RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { _id: 1, statusConnection: 1 } }).fetch(); subscribedUsers.forEach(user => { @@ -197,25 +205,29 @@ class IrcServer { } }); + // TODO Maybe use getTime()? const timestamp = Math.floor(room.ts.getTime() / 1000); const nickSpace = 510 - 29 - room.name.length; const nicksPerMessage = Math.floor(nickSpace / 20); let index = 0; - const result = []; - - while ((index * nicksPerMessage) < userIds.length) { - this.writeCommand({ - prefix: this.serverId, - command: 'SJOIN', - parameters: [timestamp, `#${ room.name }`, '+nt'], - trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') - }); - result.push(index = index + 1); - } + return (() => { + const result = []; - return result; + while ((index * nicksPerMessage) < userIds.length) { + this.writeCommand({ + prefix: this.serverId, + command: 'SJOIN', + parameters: [timestamp, `#${ room.name }`, '+nt'], + trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') + }); + + result.push(index = index + 1); + } + + return result; + })(); } joinRoom(user, room) { @@ -228,6 +240,7 @@ class IrcServer { } const userId = this.localUsersById[user._id].ircUserId; + // TODO Maybe use getTime()? const timestamp = Math.floor(room.ts.getTime() / 1000); return this.writeCommand({ @@ -282,11 +295,17 @@ class IrcServer { return; } + // TODO Attention here... + // if (Array.from(this.localUsersById).includes(!user._id)) { + // return; + // } + if (!this.localUsersById.includes(user._id)) { return; } const userId = this.localUsersById[user._id].ircUserId; + delete this.localUsersById[user._id]; delete this.localUsersByIrcId[userId]; @@ -310,49 +329,51 @@ class IrcServer { const lines = message.msg.split('\n'); - const result = []; + return (() => { + const result = []; - lines.forEach(line => { - let messageSpace; - let target; + lines.forEach(line => { + let messageSpace; + let target; - line = line.trimRight(); + line = line.trimRight(); - if (room.t === 'd') { - messageSpace = 510 - 30; + if (room.t === 'd') { + messageSpace = 510 - 30; - //TODO: Change for native ES6 filter maybe? - const targetUsername = _.find(room.usernames, username => username !== message.u.username); - const targetUser = _.find(this.ircUsers, user => user.username === targetUsername); + //TODO: Change for native ES6 filter maybe? + const targetUsername = _.find(room.usernames, username => username !== message.u.username); + const targetUser = _.find(this.ircUsers, user => user.username === targetUsername); - target = targetUser.ircUserId; - } else { - //TODO: Should only send message if there are IRC users in the room - messageSpace = 510 - 22 - room.name.length; - target = `#${ room.name }`; - } + target = targetUser.ircUserId; + } else { + //TODO: Should only send message if there are IRC users in the room + messageSpace = 510 - 22 - room.name.length; + target = `#${ room.name }`; + } - let index = 0; + let index = 0; - result.push(() => { - const elementResult = []; + result.push((() => { + const elementResult = []; - while ((index * messageSpace) < line.length) { - this.writeCommand({ - prefix: userId, - command: 'PRIVMSG', - parameters: [target], - trailer: line.substring(index * messageSpace, (index + 1) * messageSpace) - }); + while ((index * messageSpace) < line.length) { + this.writeCommand({ + prefix: userId, + command: 'PRIVMSG', + parameters: [target], + trailer: line.substring(index * messageSpace, (index + 1) * messageSpace) + }); - elementResult.push(index = index + 1); - } + elementResult.push(index = index + 1); + } - return elementResult; - }); - }); + return elementResult; + })()); + }); - return result; + return result; + })(); } logoutIrcUser(userId) { @@ -366,6 +387,7 @@ class IrcServer { RocketChat.models.Rooms.removeUsernameFromAll(user.username); + // TODO Attention about usage of 'delete' here... return delete this.ircUsers[userId]; } @@ -387,7 +409,6 @@ class IrcServer { getDirectRoom(source, target) { const rid = [source._id, target._id].sort().join(''); - const now = new Date(); RocketChat.models.Rooms.upsert({_id: rid}, { $set: { @@ -396,11 +417,11 @@ class IrcServer { $setOnInsert: { t: 'd', msgs: 0, - ts: now + ts: new Date() } }); - RocketChat.models.Subscriptions.upsert({rid, $and: [{'u._id': target._id}]}, { + RocketChat.models.Subscriptions.upsert({rid, 'u._id': target._id}, { $setOnInsert: { name: source.username, t: 'd', @@ -438,7 +459,7 @@ class IrcServer { if (command[0] === ':') { split = command.indexOf(' ', currentIndex); - result.prefix = () => { + result.prefix = (() => { if (split === -1) { currentIndex = command.length; return command.substring(1); @@ -447,13 +468,13 @@ class IrcServer { currentIndex = split + 1; return temp; } - }; + })(); } if (currentIndex !== command.length) { split = command.indexOf(' ', currentIndex); - result.command = () => { + result.command = (() => { if (split === -1) { temp = command.substring(currentIndex); currentIndex = command.length; @@ -463,10 +484,10 @@ class IrcServer { currentIndex = split + 1; return temp; } - }; + })(); } - result.parameters = () => { + result.parameters = (() => { const elementResult = []; while (currentIndex !== command.length && command[currentIndex] !== ':') { @@ -484,7 +505,7 @@ class IrcServer { } return elementResult; - }; + })(); if (currentIndex !== command.length) { result.trailer = command.substring(currentIndex + 1); @@ -541,7 +562,7 @@ class IrcServer { const command = this.parseMessage(line); - if (command.command != null) { + if (command && command.command != null) { switch (this.state) { case 'awaitingpass': if (command.command === 'PASS') { @@ -659,7 +680,7 @@ class IrcServer { // eslint-disable-next-line no-unused-vars onReceiveCAPAB(command) { // TODO: Review it - // return this.otherServerCapabilities = command.trailer.split(' '); + //return this.otherServerCapabilities = command.trailer.split(' '); } onReceiveSERVER(command) { @@ -764,36 +785,56 @@ class IrcServer { } onReceiveUID(command) { + console.log('IRC command.parameters (onReceiveUID): ', command.parameters); + if (command.parameters.length !== 9) { this.handleMalformed(command); return; } // eslint-disable-next-line no-unused-vars - const [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, userId, gecos] = command.parameters; + const [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, ircUserId, gecos] = command.parameters; const connectedTo = command.prefix; //TODO Handle nick collisions //TODO Handle verification that irc and rocketchat users are the same //TODO Handle modes - const user = Meteor.users.findOne({name: nick}); + let user = RocketChat.models.Users.findOne({name: nick}); + + /** + Nick TS collisions: + If both users are to be collided, we must issue a KILL for the existing + user to all servers. If the new user has a UID then we must also issue a + KILL for that UID back to the server sending us data causing the collision. + + If only the existing user is being collided, we must issue a KILL for the + existing user to all servers except the server sending us data. If the + existing user has a UID and the server sending us data supports TS6 then + we must also issue a KILL for the existing users UID to the server sending + us data. + + If only the new user is being collided, we must issue a KILL for the new user + back to the server sending us data if the new user has a UID. + **/ if (!user) { - Meteor.call('registerUser', { - email: `${ nick }@irc.redhat.com`, + const userId = Meteor.call('registerUser', { + email: `${ nick }@${ hostname }`, pass: '', name: nick }); - Meteor.users.update({_id: user._id}, { + RocketChat.models.Users.update({_id: userId}, { $set: { username: nick, ircOnly: true } }); + + user = RocketChat.models.Users.findOne({_id: userId}); } - Meteor.users.update({_id: user._id}, { + RocketChat.models.Users.update({_id: user._id}, { $set: { status: 'online' } @@ -801,11 +842,11 @@ class IrcServer { user.nickTimestamp = nickTimestamp; user.connectedTo = connectedTo; - user.ircUserId = userId; + user.ircUserId = ircUserId; - this.ircUsers[userId] = user; + this.ircUsers[ircUserId] = user; - return console.log(`[irc-server] Registered user ${ nick } with userId ${ userId }`); + return console.log(`[irc-server] Registered user ${ nick } with ircUserId ${ ircUserId }`); } onReceivePING(command) { @@ -917,6 +958,28 @@ class IrcServer { }); } + onReceiveKILL(command) { + const ircUserId = command.prefix; + + console.log('IRC command.parameters: ', command.parameters); + + const userForKill = this.ircUsers[ircUserId]; + if (userForKill == null || userForKill._id == null) { + return; + } + + const killedUser = this.localUsersByIrcId[ircUserId]; + if (killedUser == null) { + return; + } + + console.log(`[irc-server] Killing ${ killedUser.username }`); + + return Meteor.runAsUser(userForKill._id, () => { + + }); + } + onReceiveSQUIT(command) { let [targetServer] = command.parameters; @@ -992,6 +1055,6 @@ if (!!RocketChat.settings.get('IRC_Server_Enabled') === true) { RocketChat.callbacks.add('afterCreateRoom', IrcServerRoomCreator, RocketChat.callbacks.priority.LOW, 'irc-server-room-creator'); Meteor.startup(() => { - Meteor.setTimeout((() => ircServer.connect()), 30000); + Meteor.setTimeout((() => ircServer.connect()), 90000); }); } diff --git a/packages/rocketchat-irc-server/server/irc-server-settings.js b/packages/rocketchat-irc-server/server/irc-server-settings.js index 6398d953f373b..64a4a805b043a 100644 --- a/packages/rocketchat-irc-server/server/irc-server-settings.js +++ b/packages/rocketchat-irc-server/server/irc-server-settings.js @@ -3,8 +3,7 @@ Meteor.startup(function() { this.add('IRC_Server_Enabled', false, { type: 'boolean', i18nLabel: 'Enabled', - i18nDescription: 'IRC_Server_Enabled', - alert: 'IRC Server Support is a work in progress. Use on a production system is not recommended at this time.' + i18nDescription: 'IRC_Server_Enabled' }); this.add('IRC_Server_Host', 'irc.freenode.net', { @@ -19,31 +18,31 @@ Meteor.startup(function() { i18nDescription: 'IRC_Server_Port' }); - this.add('IRC_Server_Id', null, { + this.add('IRC_Server_Id', '', { type: 'string', i18nLabel: 'Id', i18nDescription: 'IRC_Server_Id' }); - this.add('IRC_Server_Send_Password', null, { + this.add('IRC_Server_Send_Password', '', { type: 'string', i18nLabel: 'Send_Password', i18nDescription: 'IRC_Server_Send_Password' }); - this.add('IRC_Server_Receive_Password', null, { + this.add('IRC_Server_Receive_Password', '', { type: 'string', i18nLabel: 'Receive_Password', i18nDescription: 'IRC_Server_Receive_Password' }); - this.add('IRC_Server_Name', null, { + this.add('IRC_Server_Name', '', { type: 'string', i18nLabel: 'Name', i18nDescription: 'IRC_Server_Name' }); - this.add('IRC_Server_Description', null, { + this.add('IRC_Server_Description', '', { type: 'string', i18nLabel: 'Description', i18nDescription: 'IRC_Server_Description' diff --git a/packages/rocketchat-livechat/.app/package-lock.json b/packages/rocketchat-livechat/.app/package-lock.json index 2eda1637c29ef..94e8657ad4f14 100644 --- a/packages/rocketchat-livechat/.app/package-lock.json +++ b/packages/rocketchat-livechat/.app/package-lock.json @@ -4,747 +4,885 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "abbrev": { - "version": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" - }, - "ajv": { - "version": "https://registry.npmjs.org/ajv/-/ajv-5.5.0.tgz", - "integrity": "sha1-6yhAdG6dxIvV4GOjbj/UAMXqtak=", - "requires": { - "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "fast-deep-equal": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" - } - }, - "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "aproba": { - "version": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=" - }, - "are-we-there-yet": { - "version": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "requires": { - "delegates": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - } - }, - "asn1": { - "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - }, - "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "asynckit": { - "version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, "autolinker": { - "version": "https://registry.npmjs.org/autolinker/-/autolinker-1.6.0.tgz", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.6.0.tgz", "integrity": "sha1-utN2t62OQV8i8QL8Dzf2QOZPHL8=" }, - "aws-sign2": { - "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" - }, "babel-runtime": { - "version": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "requires": { - "core-js": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "regenerator-runtime": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz" + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + }, + "dependencies": { + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } } }, - "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, "bcrypt": { - "version": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz", - "integrity": "sha1-sC3cbAtS6ha40883XVoy54DatUg=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz", + "integrity": "sha512-pRyDdo73C8Nim3jwFJ7DWe3TZCgwDfWZ6nHS5LSdU77kWbj1frruvdndP02AOavtD4y8v6Fp2dolbHgp4SDrfg==", "requires": { - "nan": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", - "node-pre-gyp": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz" - } - }, - "bcrypt-pbkdf": { - "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "optional": true, - "requires": { - "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" - } - }, - "block-stream": { - "version": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } - }, - "boom": { - "version": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz" - } - }, - "brace-expansion": { - "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "requires": { - "balanced-match": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "concat-map": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - } - }, - "caseless": { - "version": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "co": { - "version": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "code-point-at": { - "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "combined-stream": { - "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "requires": { - "delayed-stream": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - } - }, - "concat-map": { - "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "console-control-strings": { - "version": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "core-js": { - "version": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" - }, - "core-util-is": { - "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cryptiles": { - "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "requires": { - "boom": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz" + "nan": "2.6.2", + "node-pre-gyp": "0.6.36" }, "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, "boom": { - "version": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", + "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" + }, + "node-pre-gyp": { + "version": "0.6.36", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", + "integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=", + "requires": { + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.2", + "request": "2.83.0", + "rimraf": "2.6.2", + "semver": "5.4.1", + "tar": "2.2.1", + "tar-pack": "3.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "rc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz", + "integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=", + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.0" + } + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", + "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", + "requires": { + "debug": "2.6.9", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } } }, - "dashdash": { - "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" - } - }, - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } - }, - "deep-extend": { - "version": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" - }, - "delayed-stream": { - "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "ecc-jsbn": { - "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, - "requires": { - "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" - } - }, - "extend": { - "version": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "extsprintf": { - "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" - }, - "fast-json-stable-stringify": { - "version": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "forever-agent": { - "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", - "requires": { - "asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz" - } - }, - "fs.realpath": { - "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fstream": { - "version": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" - } - }, - "fstream-ignore": { - "version": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", - "requires": { - "fstream": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - } - }, - "gauge": { - "version": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "console-control-strings": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "has-unicode": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "wide-align": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz" - } - }, - "getpass": { - "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" - } - }, - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", - "requires": { - "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - }, - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "har-schema": { - "version": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "requires": { - "ajv": "https://registry.npmjs.org/ajv/-/ajv-5.5.0.tgz", - "har-schema": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" - } - }, - "has-unicode": { - "version": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "hawk": { - "version": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", - "requires": { - "boom": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "sntp": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz" - } - }, - "hoek": { - "version": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" - }, - "http-signature": { - "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "jsprim": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "sshpk": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz" - } - }, - "inflight": { - "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "block-stream": { + "version": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" } }, "inherits": { "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, - "ini": { - "version": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=" - }, - "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" - } - }, - "is-typedarray": { - "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isstream": { - "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "jquery": { - "version": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=" }, - "jsbn": { - "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "json-schema": { - "version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stringify-safe": { - "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsprim": { - "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "json-schema": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "verror": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" - } - }, - "mime-db": { - "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" - }, - "mime-types": { - "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "requires": { - "mime-db": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz" - } - }, - "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "requires": { - "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" - } - }, - "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" - } - }, "moment": { - "version": "https://registry.npmjs.org/moment/-/moment-2.19.3.tgz", - "integrity": "sha1-vbmdJw1tf9p4zA+6zoVeJ/59pp8=" - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "nan": { - "version": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", - "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" - }, - "node-pre-gyp": { - "version": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", - "integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=", - "requires": { - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "nopt": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "npmlog": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "rc": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz", - "request": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "tar": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "tar-pack": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz" - } - }, - "nopt": { - "version": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "requires": { - "abbrev": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "osenv": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz" - } - }, - "npmlog": { - "version": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", - "requires": { - "are-we-there-yet": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "console-control-strings": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "gauge": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" - } - }, - "number-is-nan": { - "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "once": { - "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } - }, - "os-homedir": { - "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-tmpdir": { - "version": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", - "requires": { - "os-homedir": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "os-tmpdir": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" - } - }, - "path-is-absolute": { - "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "performance-now": { - "version": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, - "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" - }, - "rc": { - "version": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz", - "integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=", - "requires": { - "deep-extend": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "ini": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "strip-json-comments": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" - }, - "dependencies": { - "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - } - } - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } - }, - "regenerator-runtime": { - "version": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha1-flT+W1zNXWYk6mJVw0c74JC4AuE=" - }, - "request": { - "version": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", - "requires": { - "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "hawk": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "performance-now": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "tough-cookie": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" - } - }, - "rimraf": { - "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", - "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" - } - }, - "safe-buffer": { - "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" - }, - "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=" - }, - "set-blocking": { - "version": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "signal-exit": { - "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "sntp": { - "version": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", - "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz" - } - }, - "sprintf-js": { - "version": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", - "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" - }, - "sshpk": { - "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "requires": { - "asn1": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "bcrypt-pbkdf": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "dashdash": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "ecc-jsbn": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "getpass": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" - } - }, - "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - }, - "stringstream": { - "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" - }, - "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" - } - }, - "strip-json-comments": { - "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "tar": { - "version": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "requires": { - "block-stream": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "fstream": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } - }, - "tar-pack": { - "version": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", - "integrity": "sha1-4dvAOpudO6B+iWrQJzF+tnmhCh8=", - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "fstream": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "fstream-ignore": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "tar": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "uid-number": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz" - } + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", + "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" }, "toastr": { - "version": "https://registry.npmjs.org/toastr/-/toastr-2.1.2.tgz", - "integrity": "sha1-/WkGaudXilszV3JfycfDNem2gd8=" - }, - "tough-cookie": { - "version": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "requires": { - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" - } - }, - "tunnel-agent": { - "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz", + "integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=", "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "jquery": "3.2.1" } }, - "tweetnacl": { - "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - }, - "uid-number": { - "version": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" - }, "underscore": { - "version": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" }, "underscore.string": { - "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz", "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=", "requires": { - "sprintf-js": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } - }, - "util-deprecate": { - "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=" - }, - "verror": { - "version": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" - } - }, - "wide-align": { - "version": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=", - "requires": { - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" + "sprintf-js": "1.1.1", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } } - }, - "wrappy": { - "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } } } From c219d465e5200578a6a6468554d6716925cb93e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lindo=C3=A9lio=20L=C3=A1zaro?= Date: Tue, 30 Jan 2018 10:22:59 -0200 Subject: [PATCH 12/26] Working handles for direct messages --- .meteor/versions | 6 -- packages/rocketchat-irc-server/README.md | 2 + .../server/irc-server-bridge.js | 88 +++++++++---------- 3 files changed, 45 insertions(+), 51 deletions(-) diff --git a/.meteor/versions b/.meteor/versions index cd5c5dece0677..a0c26f2dae702 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -112,11 +112,6 @@ ostrio:cookies@2.2.4 pauli:accounts-linkedin@2.1.3 pauli:linkedin-oauth@1.2.0 percolate:synced-cron@1.3.2 -practicalmeteor:chai@2.1.0_1 -practicalmeteor:loglevel@1.2.0_2 -practicalmeteor:mocha@2.4.5_6 -practicalmeteor:mocha-core@1.0.1 -practicalmeteor:sinon@1.14.1_2 promise@0.10.0 raix:eventemitter@0.1.3 raix:eventstate@0.0.4 @@ -253,7 +248,6 @@ templating@1.3.2 templating-compiler@1.3.3 templating-runtime@1.3.2 templating-tools@1.1.2 -tmeasday:test-reporter-helpers@0.2.1 todda00:friendly-slugs@0.6.0 tracker@1.1.3 twitter-oauth@1.2.0 diff --git a/packages/rocketchat-irc-server/README.md b/packages/rocketchat-irc-server/README.md index 677fecd9c7c2a..fc3b00b6f5eeb 100644 --- a/packages/rocketchat-irc-server/README.md +++ b/packages/rocketchat-irc-server/README.md @@ -7,3 +7,5 @@ docker run --name ircd -p 6667:6667 -p 7000:7000 inspircd/inspircd-docker ``` Add settings for your IRC Network on central admin at Rocket.Chat instance. + +Read more in [official InspIRCd image page at Docker Hub](https://hub.docker.com/r/inspircd/inspircd-docker). diff --git a/packages/rocketchat-irc-server/server/irc-server-bridge.js b/packages/rocketchat-irc-server/server/irc-server-bridge.js index 4e70a69f2801d..56fde0b70e73d 100644 --- a/packages/rocketchat-irc-server/server/irc-server-bridge.js +++ b/packages/rocketchat-irc-server/server/irc-server-bridge.js @@ -205,7 +205,6 @@ class IrcServer { } }); - // TODO Maybe use getTime()? const timestamp = Math.floor(room.ts.getTime() / 1000); const nickSpace = 510 - 29 - room.name.length; const nicksPerMessage = Math.floor(nickSpace / 20); @@ -213,20 +212,20 @@ class IrcServer { let index = 0; return (() => { - const result = []; + const result = []; - while ((index * nicksPerMessage) < userIds.length) { - this.writeCommand({ - prefix: this.serverId, - command: 'SJOIN', - parameters: [timestamp, `#${ room.name }`, '+nt'], - trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') - }); + while ((index * nicksPerMessage) < userIds.length) { + this.writeCommand({ + prefix: this.serverId, + command: 'SJOIN', + parameters: [timestamp, `#${ room.name }`, '+nt'], + trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') + }); - result.push(index = index + 1); - } + result.push(index = index + 1); + } - return result; + return result; })(); } @@ -240,7 +239,6 @@ class IrcServer { } const userId = this.localUsersById[user._id].ircUserId; - // TODO Maybe use getTime()? const timestamp = Math.floor(room.ts.getTime() / 1000); return this.writeCommand({ @@ -330,49 +328,49 @@ class IrcServer { const lines = message.msg.split('\n'); return (() => { - const result = []; + const result = []; - lines.forEach(line => { - let messageSpace; - let target; + lines.forEach(line => { + let messageSpace; + let target; - line = line.trimRight(); + line = line.trimRight(); - if (room.t === 'd') { - messageSpace = 510 - 30; + if (room.t === 'd') { + messageSpace = 510 - 30; - //TODO: Change for native ES6 filter maybe? - const targetUsername = _.find(room.usernames, username => username !== message.u.username); - const targetUser = _.find(this.ircUsers, user => user.username === targetUsername); + //TODO: Change for native ES6 filter maybe? + const targetUsername = _.find(room.usernames, username => username !== message.u.username); + const targetUser = _.find(this.ircUsers, user => user.username === targetUsername); - target = targetUser.ircUserId; - } else { - //TODO: Should only send message if there are IRC users in the room - messageSpace = 510 - 22 - room.name.length; - target = `#${ room.name }`; - } + target = targetUser.ircUserId; + } else { + //TODO: Should only send message if there are IRC users in the room + messageSpace = 510 - 22 - room.name.length; + target = `#${ room.name }`; + } - let index = 0; + let index = 0; - result.push((() => { - const elementResult = []; + result.push((() => { + const elementResult = []; - while ((index * messageSpace) < line.length) { - this.writeCommand({ - prefix: userId, - command: 'PRIVMSG', - parameters: [target], - trailer: line.substring(index * messageSpace, (index + 1) * messageSpace) - }); + while ((index * messageSpace) < line.length) { + this.writeCommand({ + prefix: userId, + command: 'PRIVMSG', + parameters: [target], + trailer: line.substring(index * messageSpace, (index + 1) * messageSpace) + }); - elementResult.push(index = index + 1); - } + elementResult.push(index = index + 1); + } - return elementResult; - })()); - }); + return elementResult; + })()); + }); - return result; + return result; })(); } From cfb649f7eef2126e5590d236f667d7979bfa1f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lindo=C3=A9lio=20L=C3=A1zaro?= Date: Tue, 30 Jan 2018 22:29:14 -0200 Subject: [PATCH 13/26] Working handles for direct messages --- package-lock.json | 1097 ++--------------- packages/rocketchat-irc-server/README.md | 9 +- .../server/irc-server-bridge.js | 207 ++-- .../server/irc-server.js | 1 + 4 files changed, 212 insertions(+), 1102 deletions(-) create mode 100644 packages/rocketchat-irc-server/server/irc-server.js diff --git a/package-lock.json b/package-lock.json index d3088ce6f81e4..11e5bb7382e15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -118,7 +118,7 @@ "@google-cloud/storage": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-1.4.0.tgz", - "integrity": "sha1-r1vKwqmGmJxG81Kxyhgzvns4Pds=", + "integrity": "sha512-vt1NU7D12OGYPhWfwBD1Q2qFS6Suykorlp3NLaES2W9CW6sEBWLwScxElXt8nPvonYBCFt99jP4g1AqY+0hefw==", "requires": { "@google-cloud/common": "0.13.6", "arrify": "1.0.1", @@ -391,7 +391,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "acorn": { "version": "1.2.2", @@ -499,7 +499,7 @@ "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { "micromatch": "2.3.11", @@ -509,7 +509,7 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=" + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "archiver": { "version": "2.1.1", @@ -584,7 +584,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "array-find-index": { @@ -1810,7 +1810,7 @@ "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, "backoff": { @@ -1858,7 +1858,7 @@ "base64-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha1-qRlH2h9KUW6jjltOwOw3c2deCIY=" + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==" }, "base64url": { "version": "2.0.0", @@ -1868,7 +1868,7 @@ "bcrypt": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz", - "integrity": "sha1-sC3cbAtS6ha40883XVoy54DatUg=", + "integrity": "sha512-pRyDdo73C8Nim3jwFJ7DWe3TZCgwDfWZ6nHS5LSdU77kWbj1frruvdndP02AOavtD4y8v6Fp2dolbHgp4SDrfg==", "requires": { "nan": "2.6.2", "node-pre-gyp": "0.6.36" @@ -2351,7 +2351,6 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", - "fsevents": "1.1.3", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -2385,7 +2384,7 @@ "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, "cli-cursor": { @@ -2563,7 +2562,7 @@ "configstore": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", - "integrity": "sha1-CU7mYquD+tmRdnjeEU+q6o/NypA=", + "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", "requires": { "dot-prop": "4.2.0", "graceful-fs": "4.1.11", @@ -2895,7 +2894,7 @@ "cosmiconfig": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-3.1.0.tgz", - "integrity": "sha1-ZAqUv5hH8yGABAPNJzr2BmXHM5c=", + "integrity": "sha512-zedsBhLSbPBms+kE7AH4vHg6JsKDz6epSv2/+5XHs8ILHlgDciSJfSWf8sX9aQ52Jb7KI7VswUTsLpR/G0cr2Q==", "dev": true, "requires": { "is-directory": "0.3.1", @@ -2994,7 +2993,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -3167,7 +3166,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } @@ -3307,7 +3306,7 @@ "dir-glob": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha1-CyBdK2rvmCOMooZZioIE0p0KADQ=", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", "dev": true, "requires": { "arrify": "1.0.1", @@ -3317,7 +3316,7 @@ "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { "pify": "3.0.0" @@ -3374,7 +3373,7 @@ "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "requires": { "is-obj": "1.0.1" } @@ -4203,910 +4202,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "fsevents": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", - "dev": true, - "optional": true, - "requires": { - "nan": "2.8.0", - "node-pre-gyp": "0.6.39" - }, - "dependencies": { - "abbrev": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "ajv": { - "version": "4.11.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" - } - }, - "asn1": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "balanced-match": { - "version": "0.4.2", - "bundled": true, - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "bundled": true, - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.7", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "debug": { - "version": "2.6.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true, - "dev": true, - "optional": true - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true, - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true, - "dev": true - }, - "har-schema": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true, - "dev": true - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.4", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "bundled": true, - "dev": true - }, - "mime-types": { - "version": "2.1.15", - "bundled": true, - "dev": true, - "requires": { - "mime-db": "1.27.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "node-pre-gyp": { - "version": "0.6.39", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "1.0.2", - "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" - } - }, - "npmlog": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "performance-now": { - "version": "0.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true, - "dev": true - }, - "punycode": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.2.9", - "bundled": true, - "dev": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" - } - }, - "rimraf": { - "version": "2.6.1", - "bundled": true, - "dev": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "semver": { - "version": "5.3.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "stringstream": { - "version": "0.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "dev": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "uuid": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - } - } - }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", @@ -5131,7 +4226,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "functional-red-black-tree": { @@ -5174,7 +4269,7 @@ "gcp-metadata": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.3.1.tgz", - "integrity": "sha1-MTgURW58PQ7rj4sISzNXnohvgpo=", + "integrity": "sha512-5kJPX/RXuqoLmHiOOgkSDk/LI0QaXpEvZ3pvQP4ifjGGDKZKVSOjL/GcDjXA5kLxppFCOjmmsu0Uoop9d1upaQ==", "requires": { "extend": "3.0.1", "retry-request": "3.3.1" @@ -5194,7 +4289,7 @@ "gcs-resumable-upload": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-0.8.2.tgz", - "integrity": "sha1-N98CRwQwOVp4mmN+csq8gGd66WQ=", + "integrity": "sha512-PBl1OFABYxubxfYPh000I0+JLbQzBRtNqxzgxYboIQk2tdw7BvjJ2dVukk3YH4QM6GiUwqItyNqWBuxjLH8GhA==", "requires": { "buffer-equal": "1.0.0", "configstore": "3.1.1", @@ -5329,7 +4424,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -5361,7 +4456,7 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, "globby": { @@ -5429,7 +4524,7 @@ "gonzales-pe": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.2.3.tgz", - "integrity": "sha1-QQkXA2JUMyheCu46pHgp/B++tvI=", + "integrity": "sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw==", "dev": true, "requires": { "minimist": "1.1.3" @@ -6249,7 +5344,7 @@ "gtoken": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-1.2.3.tgz", - "integrity": "sha1-VQlXG4r9QyLhJM9mz2gRUoTEdtg=", + "integrity": "sha512-wQAJflfoqSgMWrSBk9Fg86q+sd6s7y6uJhIvvIPz++RElGlMtEqsdAR2oWwZ/WTEtp7P9xFbJRrT976oRgzJ/w==", "requires": { "google-p12-pem": "0.1.2", "jws": "3.1.4", @@ -6703,7 +5798,7 @@ "hawk": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", @@ -6724,7 +5819,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, "home-or-tmp": { "version": "2.0.0", @@ -6739,7 +5834,7 @@ "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", "dev": true }, "html-tags": { @@ -6872,7 +5967,7 @@ "ignore": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha1-YSKJv7PCIOGGpYEYYY1b6MG6sCE=", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "dev": true }, "image-size": { @@ -7176,7 +6271,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-builtin-module": { @@ -7481,7 +6576,7 @@ "js-yaml": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "dev": true, "requires": { "argparse": "1.0.9", @@ -7505,7 +6600,7 @@ "jschardet": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz", - "integrity": "sha1-x9GnHtz/KDnbL57DD8XV69PBpng=" + "integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==" }, "jsesc": { "version": "1.3.0", @@ -7516,7 +6611,7 @@ "json-parse-better-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha1-UBg80bLSUnXeBp6ecbRnrJ6rlzo=", + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", "dev": true }, "json-schema": { @@ -8024,7 +7119,7 @@ "longest-streak": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha1-JCG2upOaRDu5/+v1llhaULTDji4=", + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", "dev": true }, "loose-envify": { @@ -8060,7 +7155,7 @@ "mailparser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-2.1.0.tgz", - "integrity": "sha1-zaYmHJE1DId4FzMR5GAqPNNH8K4=", + "integrity": "sha512-K5aQPX8O4pXQYv2Lg2SZQnlL+XaI4VoyxcCveUVSt5VDTPokGRouX609zttWiBeDm1dwABw41eliFlaVt8FeUQ==", "requires": { "addressparser": "1.0.1", "he": "1.1.1", @@ -8085,7 +7180,7 @@ "make-dir": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", - "integrity": "sha1-GbQ2n+SMEW9Twq+VrRAsDjnoXVE=", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", "requires": { "pify": "3.0.0" } @@ -8175,7 +7270,7 @@ "meteor-promise": { "version": "0.8.6", "resolved": "https://registry.npmjs.org/meteor-promise/-/meteor-promise-0.8.6.tgz", - "integrity": "sha1-aZehWiIfuFnUcgQ/y9yuAZBr8Z0=", + "integrity": "sha512-HP6tOr67z/9XU2Dr0F2SSr8WRTuE23AG9Dj578DCJPEYHs67OLKBviU8A8rwvbwMD7Lu2+Of+yAMz2Wd8r4yxg==", "dev": true }, "methmeth": { @@ -8218,7 +7313,7 @@ "mime-db": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.32.0.tgz", - "integrity": "sha1-SFs4SLAaPNpflotIgsB3HljglBQ=" + "integrity": "sha512-+ZWo/xZN40Tt6S+HyakUxnSOgff+JEdaneLWIm0Z6LmpCn5DMcZntLyUY5c/rTDog28LhXLKOUZKoTxTCAdBVw==" }, "mime-type": { "version": "3.0.5", @@ -8255,7 +7350,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "1.1.8" } @@ -8268,7 +7363,7 @@ "minimist-options": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha1-+6TIGRM54T7PTWG+sD8HAQPz2VQ=", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", "dev": true, "requires": { "arrify": "1.0.1", @@ -8362,7 +7457,7 @@ "moment": { "version": "2.20.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", - "integrity": "sha1-1usaRsvMFKKy+UNBEsH/iQfzE/0=" + "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" }, "moment-timezone": { "version": "0.5.14", @@ -8444,7 +7539,7 @@ "no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw=", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", "dev": true, "requires": { "lower-case": "1.1.4" @@ -8488,7 +7583,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { "hosted-git-info": "2.5.0", @@ -8526,7 +7621,7 @@ "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "requires": { "are-we-there-yet": "1.1.4", "console-control-strings": "1.1.0", @@ -8700,7 +7795,7 @@ "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha1-5OlPMR6rvIYzoeeZCBZfyiYkG2s=", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", "dev": true }, "p-try": { @@ -9025,7 +8120,7 @@ "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "poplib": { @@ -9065,7 +8160,7 @@ "postcss-custom-properties": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.2.0.tgz", - "integrity": "sha1-XZKafwbpuE4PETNBlMC6mjCs++k=", + "integrity": "sha512-eNR2h9T9ciKMoQEORrPjH33XeN/nuvVuxArOKmHtsFbGbNss631tgTrKou3/pmjAZbA4QQkhLIkPQkIk3WW+8w==", "dev": true, "requires": { "balanced-match": "1.0.0", @@ -9140,7 +8235,7 @@ "postcss-html": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.12.0.tgz", - "integrity": "sha1-ObattABd/FRk33mZwPgclbztflA=", + "integrity": "sha512-KxKUpj7AY7nlCbLcTOYxdfJnGE7QFAfU2n95ADj1Q90RM/pOLdz8k3n4avOyRFs7MDQHcRzJQWM1dehCwJxisQ==", "dev": true, "requires": { "htmlparser2": "3.9.2", @@ -9343,7 +8438,7 @@ "postcss-nested": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-3.0.0.tgz", - "integrity": "sha1-zeQL0HoHhWXz33Li3CZlhxxySFI=", + "integrity": "sha512-1xxmLHSfubuUi6xZZ0zLsNoiKfk3BWQj6fkNMaBJC529wKKLcdeCxXt6KJmDLva+trNyQNwEaE/ZWMA7cve1fA==", "dev": true, "requires": { "postcss": "6.0.16", @@ -9418,7 +8513,7 @@ "postcss-reporter": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-5.0.0.tgz", - "integrity": "sha1-oUF3/RNCgp0pFlPyeG79ZxEDMsM=", + "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", "dev": true, "requires": { "chalk": "2.3.0", @@ -9575,7 +8670,7 @@ "postcss-sass": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.2.0.tgz", - "integrity": "sha1-5VUWRB6VJrpLOApzDToC6eqnjHo=", + "integrity": "sha512-cUmYzkP747fPCQE6d+CH2l1L4VSyIlAzZsok3HPjb5Gzsq3jE+VjpAdGlPsnQ310WKWI42sw+ar0UNN59/f3hg==", "dev": true, "requires": { "gonzales-pe": "4.2.3", @@ -9816,7 +8911,7 @@ "postcss-sorting": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-3.1.0.tgz", - "integrity": "sha1-r3yQ7nOtElaaV2ZOrwZzXC4lvsA=", + "integrity": "sha512-YCPTcJwGIInF1LpMD1lIYvMHTGUL4s97o/OraA6eKvoauhhk6vjwOWDDjm6uRKqug/kyDPMKEzmYZ6FtW6RDgw==", "dev": true, "requires": { "lodash": "4.17.4", @@ -9913,7 +9008,7 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=" + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" }, "process-nextick-args": { "version": "1.0.7", @@ -9929,7 +9024,7 @@ "prom-client": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-10.2.2.tgz", - "integrity": "sha1-drOXIHEOwQeW185gE1tdXa+/9hU=", + "integrity": "sha512-d3qCBK41qZx00/WVzWOX4tau9FinCztqaECZiGuMI5vGYD//5VSdKMOZPRQKjVh5RkI4Ex98DI0YPsoFnEo1QQ==", "requires": { "tdigest": "0.1.1" } @@ -10025,7 +9120,7 @@ "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "querystring": { "version": "0.2.0", @@ -10041,7 +9136,7 @@ "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "dev": true, "requires": { "is-number": "3.0.0", @@ -10143,7 +9238,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -10210,7 +9305,7 @@ "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha1-DDNtOYBVPXVcObWGrjsgqknIK38=", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", "dev": true }, "regenerator-runtime": { @@ -10221,7 +9316,7 @@ "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha1-HkmWg3Ix2ot/PPQRTXG1aRoGgN0=", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", "dev": true, "requires": { "babel-runtime": "6.26.0", @@ -10232,7 +9327,7 @@ "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, "requires": { "is-equal-shallow": "0.1.3" @@ -10275,7 +9370,7 @@ "remark": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-8.0.0.tgz", - "integrity": "sha1-KHtt8v4RkOJjwdFeSG0/qDVZTW0=", + "integrity": "sha512-K0PTsaZvJlXTl9DN6qYlvjTkqSZBFELhROZMrblm2rB+085flN84nz4g/BscKRMqDvhzlK1oQ/xnWQumdeNZYw==", "dev": true, "requires": { "remark-parse": "4.0.0", @@ -10286,7 +9381,7 @@ "remark-parse": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-4.0.0.tgz", - "integrity": "sha1-mfHwSa+sgDgjZuLg0L1VQp3UXYs=", + "integrity": "sha512-XZgICP2gJ1MHU7+vQaRM+VA9HEL3X253uwUM/BGgx3iv6TH2B3bF3B8q00DKcyP9YrJV+/7WOWEWBFF/u8cIsw==", "dev": true, "requires": { "collapse-white-space": "1.0.3", @@ -10309,7 +9404,7 @@ "remark-stringify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-4.0.0.tgz", - "integrity": "sha1-RDGITAQY8RLaRJkbTjVs/jf6zYc=", + "integrity": "sha512-xLuyKTnuQer3ke9hkU38SUYLiTmS078QOnoFavztmbt/pAJtNSkNtFgR0U//uCcmG0qnyxao+PDuatQav46F1w==", "dev": true, "requires": { "ccount": "1.0.2", @@ -10364,7 +9459,7 @@ "request": { "version": "2.83.0", "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", "requires": { "aws-sign2": "0.7.0", "aws4": "1.6.0", @@ -10428,7 +9523,7 @@ "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", "dev": true, "requires": { "path-parse": "1.0.5" @@ -10624,7 +9719,7 @@ "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "requires": { "glob": "7.1.2" } @@ -10665,7 +9760,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "safe-json-stringify": { "version": "1.0.4", @@ -10930,7 +10025,7 @@ "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=" + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" }, "send": { "version": "0.1.0", @@ -11048,7 +10143,7 @@ "slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0" @@ -11070,7 +10165,7 @@ "sntp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "requires": { "hoek": "4.2.0" } @@ -11098,7 +10193,7 @@ "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { "source-map": "0.5.7" @@ -11150,13 +10245,13 @@ "specificity": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.2.tgz", - "integrity": "sha1-meZRHs7vD42bV5JJN6rCyxPRPEI=", + "integrity": "sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A==", "dev": true }, "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k=", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "requires": { "through": "2.3.8" @@ -11174,7 +10269,7 @@ "split2": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", - "integrity": "sha1-GGsldbz4PoW30YRldWI47k7kJJM=", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", "dev": true, "requires": { "through2": "2.0.3" @@ -11218,7 +10313,7 @@ "stackframe": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", - "integrity": "sha1-NXskqZL5Qny6a1RdlqFO0svKGHs=", + "integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==", "dev": true } } @@ -11310,7 +10405,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "requires": { "safe-buffer": "5.1.1" } @@ -11377,7 +10472,7 @@ "stylelint": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-8.4.0.tgz", - "integrity": "sha1-wtuusXI2kXgZ+SBuHA31/d9vg8M=", + "integrity": "sha512-56hPH5mTFnk8LzlEuTWq0epa34fHuS54UFYQidBOFt563RJBNi1nz1F2HK2MoT1X1waq47milvRsRahFCCJs/Q==", "dev": true, "requires": { "autoprefixer": "7.2.5", @@ -11467,7 +10562,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -11541,7 +10636,7 @@ "meow": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.0.tgz", - "integrity": "sha1-/VhV3QCNtbksVSCC2xwwfLogsp0=", + "integrity": "sha512-Me/kel335m6vMKmEmA6c87Z6DUFW3JqkINRnxkbC+A/PUm0D5Fl2dEBQrPKnqCL9Te/CIa1MUt/0InMJhuC/sw==", "dev": true, "requires": { "camelcase-keys": "4.2.0", @@ -11574,7 +10669,7 @@ "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { "pify": "3.0.0" @@ -11636,7 +10731,7 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "source-map": { @@ -11648,7 +10743,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", @@ -11696,7 +10791,7 @@ "stylelint-order": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-0.8.0.tgz", - "integrity": "sha1-SdpWFcuR7Qd+vSdGh/TfPW/utOQ=", + "integrity": "sha512-XwJO7rIAt/hnBJjOsDgEwNSeqw+5jE22da4pVKaePbojM9bGwhOoAWV7Q2BL8caOg81IlTesmYCEf8s0+2Cc5g==", "dev": true, "requires": { "lodash": "4.17.4", @@ -11902,7 +10997,7 @@ "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { "ajv": "5.5.2", @@ -11954,7 +11049,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", @@ -11994,7 +11089,7 @@ "tar-pack": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", - "integrity": "sha1-4dvAOpudO6B+iWrQJzF+tnmhCh8=", + "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", "requires": { "debug": "2.6.9", "fstream": "1.0.11", @@ -12046,7 +11141,7 @@ "text-extensions": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.7.0.tgz", - "integrity": "sha1-+qq6JiXtdG1WiiPk0KrNm/CKizk=", + "integrity": "sha512-AKXZeDq230UaSzaO5s3qQUZOaC7iKbzq0jOFL614R7d9R593HLqAOL0cYoqLdkNrjBSOdmoQI06yigq1TSBXAg==", "dev": true }, "text-table": { @@ -12083,12 +11178,12 @@ "tlds": { "version": "1.197.0", "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.197.0.tgz", - "integrity": "sha1-XlRjoqDXhICusXaLZhHk87wid40=" + "integrity": "sha512-zCyB24s6LWQV+qIhNnL/mODj5vpZhZYIOywuweXTsMet2yFgTtOQtjxxCcwTNtSiUj5wjWJLdi6BTn9EHwvfkA==" }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "1.0.2" @@ -12520,7 +11615,7 @@ "unified": { "version": "6.1.6", "resolved": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", - "integrity": "sha1-Xqf4B6CJjx+Kze7+XyX6oBDMQrE=", + "integrity": "sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w==", "dev": true, "requires": { "bail": "1.0.2", @@ -12588,7 +11683,7 @@ "unist-util-visit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", - "integrity": "sha1-Qcp8gpgf0c5sdiqsOX/CTjVxFEQ=", + "integrity": "sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ==", "dev": true, "requires": { "unist-util-is": "2.1.1" @@ -12645,7 +11740,7 @@ "urijs": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.0.tgz", - "integrity": "sha1-2KooTQ50aXA6aYitBFxMv98IraA=", + "integrity": "sha512-Qs2odXn0hST5VSPVjpi73CMqtbAoanahaqWBujGU+IyMrMqpWcIhDewxQRhCkmqYxuyvICDcSuLdv2O7ncWBGw==", "dev": true }, "urix": { @@ -12707,7 +11802,7 @@ "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=" + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" }, "validate-npm-package-license": { "version": "3.0.1", @@ -12761,7 +11856,7 @@ "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha1-5i2OcrIOg8MkvGxnJ47ickiL+Eo=", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", "dev": true, "requires": { "is-buffer": "1.1.6", @@ -12779,7 +11874,7 @@ "vfile-message": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", - "integrity": "sha1-pq2wR06kAPol2Snx1nOr6moX41k=", + "integrity": "sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw==", "dev": true, "requires": { "unist-util-stringify-position": "1.1.1" @@ -12922,7 +12017,7 @@ "wide-align": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "requires": { "string-width": "1.0.2" } @@ -12955,7 +12050,7 @@ "wolfy87-eventemitter": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.4.tgz", - "integrity": "sha1-UCHSlS02EcvNGVFJcR2bWVzRHUg=" + "integrity": "sha512-yUOUSIzZxqBeu6VdnigqYHwwjy5N3CRX5XSHh/YcVpy+Qsx+HkHaEWdmdyAr3NvyBYDraOa5EfNIbu47T5QzIA==" }, "wordwrap": { "version": "0.0.3", @@ -12988,7 +12083,7 @@ "write-file-atomic": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha1-H/YVdcLipOjlENb6TiQ8zhg5mas=", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", "requires": { "graceful-fs": "4.1.11", "imurmurhash": "0.1.4", diff --git a/packages/rocketchat-irc-server/README.md b/packages/rocketchat-irc-server/README.md index fc3b00b6f5eeb..c7f35fab15cd2 100644 --- a/packages/rocketchat-irc-server/README.md +++ b/packages/rocketchat-irc-server/README.md @@ -3,7 +3,14 @@ Provides an IRC Network environmet with Docker for tests. ``` -docker run --name ircd -p 6667:6667 -p 7000:7000 inspircd/inspircd-docker +docker pull inspircd/inspircd-docker +docker run --name ircd -p 6667:6667 -p 6697:6697 -p 7000:7000 -e "INSP_NET_SUFFIX=.rocket.chat" -e "INSP_NET_NAME=RocketChatNetwork" -e "INSP_SERVER_NAME=irc.rocket.chat" -e "INSP_SERVICES_PASSWORD=password" inspircd/inspircd-docker +``` + +You may also use a more simple container with services enabled + +``` +docker run --name ircd -p 6667:6667 -p 6697:6697 -p 7000:7000 -e "INSP_SERVICES_PASSWORD=password" inspircd/inspircd-docker ``` Add settings for your IRC Network on central admin at Rocket.Chat instance. diff --git a/packages/rocketchat-irc-server/server/irc-server-bridge.js b/packages/rocketchat-irc-server/server/irc-server-bridge.js index 56fde0b70e73d..30648e1bf77c9 100644 --- a/packages/rocketchat-irc-server/server/irc-server-bridge.js +++ b/packages/rocketchat-irc-server/server/irc-server-bridge.js @@ -1,54 +1,8 @@ import net from 'net'; import _ from 'underscore'; -// const bind = function(f) { -// const g = Meteor.bindEnvironment((self, ...args) => f.apply(self, args)); -// return function(...args) { return g(this, ...Array.from(args)); }; -// }; - class IrcServer { constructor() { - // this.connect = bind(this.connect); - // this.disconnect = bind(this.disconnect); - // this.onConnect = bind(this.onConnect); - // this.onClose = bind(this.onClose); - // this.onTimeout = bind(this.onTimeout); - // this.onError = bind(this.onError); - // this.cleanup = bind(this.cleanup); - // this.burst = bind(this.burst); - // this.sendUser = bind(this.sendUser); - // this.sendRoom = bind(this.sendRoom); - // this.joinRoom = bind(this.joinRoom); - // this.loginUser = bind(this.loginUser); - // this.leaveRoom = bind(this.leaveRoom); - // this.createRoom = bind(this.createRoom); - // this.logoutUser = bind(this.logoutUser); - // this.sendMessage = bind(this.sendMessage); - // this.logoutIrcUser = bind(this.logoutIrcUser); - // this.cleanupIrcServer = bind(this.cleanupIrcServer); - // this.getTime = bind(this.getTime); - // this.parseMessage = bind(this.parseMessage); - // this.writeCommand = bind(this.writeCommand); - // this.handleMalformed = bind(this.handleMalformed); - // this.onReceiveRawMessage = bind(this.onReceiveRawMessage); - // this.onReceivePASS = bind(this.onReceivePASS); - // this.onReceiveCAPAB = bind(this.onReceiveCAPAB); - // this.onReceiveSERVER = bind(this.onReceiveSERVER); - // this.onReceiveSVINFO = bind(this.onReceiveSVINFO); - // this.onReceiveSID = bind(this.onReceiveSID); - // this.onReceiveSJOIN = bind(this.onReceiveSJOIN); - // this.onReceiveUID = bind(this.onReceiveUID); - // this.onReceivePING = bind(this.onReceivePING); - // this.onReceivePONG = bind(this.onReceivePONG); - // this.onReceiveEOB = bind(this.onReceiveEOB); - // this.onReceiveJOIN = bind(this.onReceiveJOIN); - // this.onReceivePART = bind(this.onReceivePART); - // this.onReceiveQUIT = bind(this.onReceiveQUIT); - // this.onReceiveINVITE = bind(this.onReceiveINVITE); - // this.onReceiveKICK = bind(this.onReceiveKICK); - // this.onReceiveSQUIT = bind(this.onReceiveSQUIT); - // this.onReceivePRIVMSG = bind(this.onReceivePRIVMSG); - this.ircPort = RocketChat.settings.get('IRC_Server_Port'); this.ircHost = RocketChat.settings.get('IRC_Server_Host'); this.serverId = RocketChat.settings.get('IRC_Server_Id'); @@ -77,6 +31,7 @@ class IrcServer { this.nextUid = parseInt('a00001', 36); this.socket = new net.Socket; + // TODO It probably should be removed (setNoDelay)... this.socket.setNoDelay(); this.socket.setEncoding('utf-8'); this.socket.setKeepAlive(true); @@ -211,22 +166,37 @@ class IrcServer { let index = 0; - return (() => { - const result = []; + // return (() => { + // const result = []; - while ((index * nicksPerMessage) < userIds.length) { - this.writeCommand({ - prefix: this.serverId, - command: 'SJOIN', - parameters: [timestamp, `#${ room.name }`, '+nt'], - trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') - }); + // while ((index * nicksPerMessage) < userIds.length) { + // this.writeCommand({ + // prefix: this.serverId, + // command: 'SJOIN', + // parameters: [timestamp, `#${ room.name }`, '+nt'], + // trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') + // }); - result.push(index = index + 1); - } + // result.push(index = index + 1); + // } - return result; - })(); + // return result; + // })(); + + const result = []; + + while ((index * nicksPerMessage) < userIds.length) { + this.writeCommand({ + prefix: this.serverId, + command: 'SJOIN', + parameters: [timestamp, `#${ room.name }`, '+nt'], + trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') + }); + + result.push(index = index + 1); + } + + return result; } joinRoom(user, room) { @@ -259,6 +229,7 @@ class IrcServer { this.sendUser(user); + // TODO It should be decomposed return RocketChat.models.Rooms.findWithUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } }).forEach(room => this.joinRoom(user, room)); } @@ -445,7 +416,7 @@ class IrcServer { parseMessage(command) { let currentIndex = 0; - let temp; + // let temp; let split; const result = {}; @@ -457,53 +428,83 @@ class IrcServer { if (command[0] === ':') { split = command.indexOf(' ', currentIndex); - result.prefix = (() => { - if (split === -1) { - currentIndex = command.length; - return command.substring(1); - } else { - temp = command.substring(currentIndex+1, split); - currentIndex = split + 1; - return temp; - } - })(); + // result.prefix = (() => { + // if (split === -1) { + // currentIndex = command.length; + // return command.substring(1); + // } else { + // temp = command.substring(currentIndex+1, split); + // currentIndex = split + 1; + // return temp; + // } + // })(); + + if (split === -1) { + currentIndex = command.length; + result.prefix = command.substring(1); + } else { + result.prefix = command.substring(currentIndex+1, split); + currentIndex = split + 1; + } } if (currentIndex !== command.length) { split = command.indexOf(' ', currentIndex); - result.command = (() => { - if (split === -1) { - temp = command.substring(currentIndex); - currentIndex = command.length; - return temp; - } else { - temp = command.substring(currentIndex, split); - currentIndex = split + 1; - return temp; - } - })(); + // result.command = (() => { + // if (split === -1) { + // temp = command.substring(currentIndex); + // currentIndex = command.length; + // return temp; + // } else { + // temp = command.substring(currentIndex, split); + // currentIndex = split + 1; + // return temp; + // } + // })(); + + if (split === -1) { + result.command = command.substring(currentIndex); + currentIndex = command.length; + } else { + result.command = command.substring(currentIndex, split); + currentIndex = split + 1; + } } - result.parameters = (() => { - const elementResult = []; + // result.parameters = (() => { + // const elementResult = []; - while (currentIndex !== command.length && command[currentIndex] !== ':') { - split = command.indexOf(' ', currentIndex); + // while (currentIndex !== command.length && command[currentIndex] !== ':') { + // split = command.indexOf(' ', currentIndex); - if (split === -1) { - temp = command.substring(currentIndex); - currentIndex = command.length; - elementResult.push(temp); - } else { - temp = command.substring(currentIndex, split); - currentIndex = split + 1; - elementResult.push(temp); - } - } + // if (split === -1) { + // temp = command.substring(currentIndex); + // currentIndex = command.length; + // elementResult.push(temp); + // } else { + // temp = command.substring(currentIndex, split); + // currentIndex = split + 1; + // elementResult.push(temp); + // } + // } - return elementResult; - })(); + // return elementResult; + // })(); + + result.parameters = []; + + while (currentIndex !== command.length && command[currentIndex] !== ':') { + split = command.indexOf(' ', currentIndex); + + if (split === -1) { + currentIndex = command.length; + result.parameters.push(command.substring(currentIndex)); + } else { + currentIndex = split + 1; + result.parameters.push(command.substring(currentIndex, split)); + } + } if (currentIndex !== command.length) { result.trailer = command.substring(currentIndex + 1); @@ -849,7 +850,13 @@ class IrcServer { onReceivePING(command) { const source = command.trailer; - return this.writeCommand({prefix: this.serverId, command: 'PONG', parameters: [this.serverName], trailer: source}); + + return this.writeCommand({ + prefix: this.serverId, + command: 'PONG', + parameters: [this.serverName], + trailer: source + }); } onReceivePONG(command) { @@ -974,7 +981,7 @@ class IrcServer { console.log(`[irc-server] Killing ${ killedUser.username }`); return Meteor.runAsUser(userForKill._id, () => { - + // TODO Kill user }); } @@ -1053,6 +1060,6 @@ if (!!RocketChat.settings.get('IRC_Server_Enabled') === true) { RocketChat.callbacks.add('afterCreateRoom', IrcServerRoomCreator, RocketChat.callbacks.priority.LOW, 'irc-server-room-creator'); Meteor.startup(() => { - Meteor.setTimeout((() => ircServer.connect()), 90000); + Meteor.setTimeout((() => ircServer.connect()), 30000); }); } diff --git a/packages/rocketchat-irc-server/server/irc-server.js b/packages/rocketchat-irc-server/server/irc-server.js new file mode 100644 index 0000000000000..4eb9724ad57e2 --- /dev/null +++ b/packages/rocketchat-irc-server/server/irc-server.js @@ -0,0 +1 @@ +// TODO Refactoring - transfer IrcServer class (irc-server-bridge) to your specific file From a99c571ca4c100c19fcdb5dd9a357545ca303828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lindo=C3=A9lio=20L=C3=A1zaro?= Date: Mon, 5 Feb 2018 06:40:22 -0200 Subject: [PATCH 14/26] Working handles for direct messages --- packages/rocketchat-irc-server/README.md | 22 +++-- .../server/irc-server-bridge.js | 85 ++++++++++--------- .../server/irc-server-settings.js | 14 +-- 3 files changed, 65 insertions(+), 56 deletions(-) diff --git a/packages/rocketchat-irc-server/README.md b/packages/rocketchat-irc-server/README.md index c7f35fab15cd2..eebd8dfeea8f0 100644 --- a/packages/rocketchat-irc-server/README.md +++ b/packages/rocketchat-irc-server/README.md @@ -1,18 +1,26 @@ **IRC Server Federation** -Provides an IRC Network environmet with Docker for tests. +Provides an IRC Network environmet (using Docker) linking servers ``` docker pull inspircd/inspircd-docker -docker run --name ircd -p 6667:6667 -p 6697:6697 -p 7000:7000 -e "INSP_NET_SUFFIX=.rocket.chat" -e "INSP_NET_NAME=RocketChatNetwork" -e "INSP_SERVER_NAME=irc.rocket.chat" -e "INSP_SERVICES_PASSWORD=password" inspircd/inspircd-docker -``` - -You may also use a more simple container with services enabled +docker run --name ircd -p 6667:6667 -p 6697:6697 -p 7000:7000 +-e "INSP_NET_SUFFIX=.example.com" +-e "INSP_NET_NAME=LocalNetwork" +-e "INSP_SERVER_NAME=irc.example.com" +-e "INSP_ENABLE_DNSBL=no" +-e "INSP_LINK1_NAME=irc.example.com" +-e "INSP_LINK1_IPADDR=0.0.0.0" +-e "INSP_LINK1_PORT=7000" +-e "INSP_LINK1_SENDPASS=password" +-e "INSP_LINK1_RECVPASS=password" +-e "INSP_LINK1_TLS_ON=no" +inspircd/inspircd-docker -``` -docker run --name ircd -p 6667:6667 -p 6697:6697 -p 7000:7000 -e "INSP_SERVICES_PASSWORD=password" inspircd/inspircd-docker +docker run --name ircd -p 6667:6667 -p 7000:7000 -e "INSP_NET_SUFFIX=.example.com" -e "INSP_NET_NAME=LocalNetwork" -e "INSP_SERVER_NAME=irc.example.com" -e "INSP_ENABLE_DNSBL=no" -e "INSP_LINK1_NAME=irc.example.com" -e "INSP_LINK1_IPADDR=0.0.0.0" -e "INSP_LINK1_PORT=7000" -e "INSP_LINK1_SENDPASS=password" -e "INSP_LINK1_RECVPASS=password" -e "INSP_LINK1_TLS_ON=no" inspircd/inspircd-docker ``` Add settings for your IRC Network on central admin at Rocket.Chat instance. +Connect your IRC client (e.g mIRC, irssi etc) using the port 6667 and connect your Rocket.Chat instance at port 7000. Read more in [official InspIRCd image page at Docker Hub](https://hub.docker.com/r/inspircd/inspircd-docker). diff --git a/packages/rocketchat-irc-server/server/irc-server-bridge.js b/packages/rocketchat-irc-server/server/irc-server-bridge.js index 30648e1bf77c9..5f4a933807d0f 100644 --- a/packages/rocketchat-irc-server/server/irc-server-bridge.js +++ b/packages/rocketchat-irc-server/server/irc-server-bridge.js @@ -47,19 +47,19 @@ class IrcServer { this.state = 'waitingforconnection'; } - connect() { + connect = () => { console.log(`[irc-server] Attempting connection to IRC on ${ this.ircHost }:${ this.ircPort }`); this.socket.connect(this.ircPort, this.ircHost, this.onConnect); return this.state = 'connecting'; } - disconnect() { + disconnect = () => { this.socket.end(); this.state = 'waitingforconnection'; return this.cleanup(); } - onConnect() { + onConnect = () => { this.writeCommand({ command: 'PASS', parameters: [this.sendPassword, 'TS', 6, this.serverId] @@ -78,14 +78,14 @@ class IrcServer { return this.state = 'awaitingpass'; } - onClose() { + onClose = () => { console.log('[irc-server] Socket closed, cleaning up state'); this.state = 'waitingforconnection'; return this.cleanup(); } - onTimeout() { + onTimeout = () => { if (this.state === 'connected' || this.state === 'bursting') { return this.writeCommand({ command: 'PING', @@ -97,12 +97,12 @@ class IrcServer { } } - onError(error) { + onError = (error) => { console.log(error); return console.log(`[irc-server] Socket error: ${ error.message }`); } - cleanup() { + cleanup = () => { this.partialMessage = ''; if (this.ircServers.length > 0) { @@ -114,7 +114,7 @@ class IrcServer { return this.localUsersByIrcId = {}; } - burst() { + burst = () => { const users = RocketChat.models.Users.find({statusConnection: 'online'}, { fields: { _id: 1, username: 1, status: 1, name: 1}}).fetch(); const rooms = RocketChat.models.Rooms.find({}, {fields: { ts: 1, name: 1, usernames: 1, t: 1 } }).fetch(); @@ -127,7 +127,7 @@ class IrcServer { }); } - sendUser(user) { + sendUser = (user) => { const counterString = this.nextUid.toString().toUpperCase(); this.nextUid = this.nextUid + 1; @@ -145,7 +145,7 @@ class IrcServer { }); } - sendRoom(room) { + sendRoom = (room) => { if (room.t === 'd') { return; } @@ -199,7 +199,7 @@ class IrcServer { return result; } - joinRoom(user, room) { + joinRoom = (user, room) => { if (this.state !== 'connected') { return; } @@ -218,7 +218,7 @@ class IrcServer { }); } - loginUser(user) { + loginUser = (user) => { if (this.state !== 'connected') { return; } @@ -233,7 +233,7 @@ class IrcServer { return RocketChat.models.Rooms.findWithUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } }).forEach(room => this.joinRoom(user, room)); } - leaveRoom(user, room) { + leaveRoom = (user, room) => { if (this.state !== 'connected') { return; } @@ -251,7 +251,7 @@ class IrcServer { }); } - createRoom(owner, room) { + createRoom = (owner, room) => { if (room.t === 'd' || this.localUsersById[owner._id] === undefined) { return; } @@ -259,7 +259,7 @@ class IrcServer { return this.sendRoom(room); } - logoutUser(user) { + logoutUser = (user) => { if (this.state !== 'connected') { return; } @@ -285,7 +285,8 @@ class IrcServer { }); } - sendMessage(message, room) { + // TODO Refactoring this self function + sendMessage = (message, room) => { if (this.state !== 'connected') { return; } @@ -345,7 +346,7 @@ class IrcServer { })(); } - logoutIrcUser(userId) { + logoutIrcUser = (userId) => { const user = this.ircUsers[userId]; Meteor.users.update({_id: user._id}, { @@ -360,7 +361,7 @@ class IrcServer { return delete this.ircUsers[userId]; } - cleanupIrcServer(serverId) { + cleanupIrcServer = (serverId) => { const disconnectedIds = []; let queue = [serverId]; @@ -376,7 +377,7 @@ class IrcServer { return _.filter(this.ircUsers, user => disconnectedIds.includes(user.connectedTo)).forEach(this.logoutIrcUser); } - getDirectRoom(source, target) { + getDirectRoom = (source, target) => { const rid = [source._id, target._id].sort().join(''); RocketChat.models.Rooms.upsert({_id: rid}, { @@ -410,11 +411,11 @@ class IrcServer { }; } - getTime() { + static getTime() { return Math.floor(Date.now() / 1000); } - parseMessage(command) { + parseMessage = (command) => { let currentIndex = 0; // let temp; let split; @@ -513,7 +514,7 @@ class IrcServer { return result; } - writeCommand(command) { + writeCommand = (command) => { let buffer = command.prefix != null ? `:${ command.prefix } ` : ''; buffer += command.command; @@ -532,11 +533,11 @@ class IrcServer { return this.socket.write(`${ buffer }\r\n`); } - handleMalformed(command) { + static handleMalformed(command) { return console.log(`[irc-server] Received invalid command: ${ command }`); } - onReceiveRawMessage(data) { + onReceiveRawMessage = (data) => { const dataString = data.toString(); const lines = dataString.split('\r\n'); @@ -652,7 +653,7 @@ class IrcServer { return this.partialMessage = newPartialMessage; } - onReceivePASS(command) { + onReceivePASS = (command) => { if (command.parameters.length !== 4) { this.handleMalformed(command); this.disconnect(); @@ -677,12 +678,12 @@ class IrcServer { } // eslint-disable-next-line no-unused-vars - onReceiveCAPAB(command) { + onReceiveCAPAB = (command) => { // TODO: Review it //return this.otherServerCapabilities = command.trailer.split(' '); } - onReceiveSERVER(command) { + onReceiveSERVER = (command) => { if (command.parameters.length !== 2 || command.trailer == null) { this.handleMalformed(command); this.disconnect(); @@ -696,7 +697,7 @@ class IrcServer { return this.ircServers[this.otherServerId].serverName = serverName; } - onReceiveSVINFO(command) { + onReceiveSVINFO = (command) => { if (!command.parameters || command.parameters.length !== 3 || command.trailer == null) { this.handleMalformed(command); this.disconnect(); @@ -729,7 +730,7 @@ class IrcServer { return this.state = 'connected'; } - onReceiveSID(command) { + onReceiveSID = (command) => { if (!command.parameters || command.parameters.length !== 3 || command.trailer == null || command.prefix == null) { this.handleMalformed(command); return; @@ -748,7 +749,7 @@ class IrcServer { return console.log(`[irc-server] New server connected: ${ serverName } via ${ this.ircServers[connectedTo].serverName }`); } - onReceiveSJOIN(command) { + onReceiveSJOIN = (command) => { if (command.parameters.length !== 3 || command.trailer == null) { this.handleMalformed(command); return; @@ -783,7 +784,7 @@ class IrcServer { return RocketChat.models.Rooms.addUsernamesById(room._id, _.map(users, user => user.username)); } - onReceiveUID(command) { + onReceiveUID = (command) => { console.log('IRC command.parameters (onReceiveUID): ', command.parameters); if (command.parameters.length !== 9) { @@ -848,7 +849,7 @@ class IrcServer { return console.log(`[irc-server] Registered user ${ nick } with ircUserId ${ ircUserId }`); } - onReceivePING(command) { + onReceivePING = (command) => { const source = command.trailer; return this.writeCommand({ @@ -859,7 +860,7 @@ class IrcServer { }); } - onReceivePONG(command) { + onReceivePONG = (command) => { // eslint-disable-next-line no-unused-vars let targetServerId; @@ -872,13 +873,13 @@ class IrcServer { return targetServerId = command.trailer; } - onReceiveEOB(command) { + onReceiveEOB = (command) => { const serverId = command.prefix; return console.log(`[irc-server] Finished receiving burst from ${ this.ircServers[serverId].serverName }`); } - onReceiveJOIN(command) { + onReceiveJOIN = (command) => { const userId = command.prefix; // eslint-disable-next-line no-unused-vars @@ -887,14 +888,14 @@ class IrcServer { return RocketChat.models.Rooms.addUsernameByName(channel.substring(1), this.ircUsers[userId].username); } - onReceivePART(command) { + onReceivePART = (command) => { const userId = command.prefix; const [channel] = command.parameters; return RocketChat.models.Rooms.removeUsernameByName(channel.substring(1), this.ircUsers[userId].username); } - onReceiveQUIT(command) { + onReceiveQUIT = (command) => { const userId = command.prefix; // eslint-disable-next-line no-unused-vars @@ -903,7 +904,7 @@ class IrcServer { return this.logoutIrcUser(userId); } - onReceiveINVITE(command) { + onReceiveINVITE = (command) => { const invitingUserId = command.prefix; // eslint-disable-next-line no-unused-vars @@ -934,7 +935,7 @@ class IrcServer { }); } - onReceiveKICK(command) { + onReceiveKICK = (command) => { const kickingUserId = command.prefix; const [channel, kickedUserId] = command.parameters; @@ -963,7 +964,7 @@ class IrcServer { }); } - onReceiveKILL(command) { + onReceiveKILL = (command) => { const ircUserId = command.prefix; console.log('IRC command.parameters: ', command.parameters); @@ -985,7 +986,7 @@ class IrcServer { }); } - onReceiveSQUIT(command) { + onReceiveSQUIT = (command) => { let [targetServer] = command.parameters; // eslint-disable-next-line no-unused-vars @@ -999,7 +1000,7 @@ class IrcServer { return this.cleanupIrcServer(targetServer); } - onReceivePRIVMSG(command) { + onReceivePRIVMSG = (command) => { let room; const userId = command.prefix; diff --git a/packages/rocketchat-irc-server/server/irc-server-settings.js b/packages/rocketchat-irc-server/server/irc-server-settings.js index 64a4a805b043a..7cda8743b1505 100644 --- a/packages/rocketchat-irc-server/server/irc-server-settings.js +++ b/packages/rocketchat-irc-server/server/irc-server-settings.js @@ -6,43 +6,43 @@ Meteor.startup(function() { i18nDescription: 'IRC_Server_Enabled' }); - this.add('IRC_Server_Host', 'irc.freenode.net', { + this.add('IRC_Server_Host', '172.17.0.1', { type: 'string', i18nLabel: 'Host', i18nDescription: 'IRC_Server_Host' }); - this.add('IRC_Server_Port', 6667, { + this.add('IRC_Server_Port', 7000, { type: 'int', i18nLabel: 'Port', i18nDescription: 'IRC_Server_Port' }); - this.add('IRC_Server_Id', '', { + this.add('IRC_Server_Id', '777', { type: 'string', i18nLabel: 'Id', i18nDescription: 'IRC_Server_Id' }); - this.add('IRC_Server_Send_Password', '', { + this.add('IRC_Server_Send_Password', 'password', { type: 'string', i18nLabel: 'Send_Password', i18nDescription: 'IRC_Server_Send_Password' }); - this.add('IRC_Server_Receive_Password', '', { + this.add('IRC_Server_Receive_Password', 'password', { type: 'string', i18nLabel: 'Receive_Password', i18nDescription: 'IRC_Server_Receive_Password' }); - this.add('IRC_Server_Name', '', { + this.add('IRC_Server_Name', 'irc.example.com', { type: 'string', i18nLabel: 'Name', i18nDescription: 'IRC_Server_Name' }); - this.add('IRC_Server_Description', '', { + this.add('IRC_Server_Description', 'IRC Network', { type: 'string', i18nLabel: 'Description', i18nDescription: 'IRC_Server_Description' From 330557cf50bb134711eb67d22eac0e5fa5a9a008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lindo=C3=A9lio=20L=C3=A1zaro?= Date: Tue, 6 Feb 2018 08:58:18 -0200 Subject: [PATCH 15/26] Working handles for direct messages --- .eslintrc | 1 + package-lock.json | 12760 ++++++++++++++++ package.json | 1 + packages/rocketchat-irc-server/README.md | 18 +- .../server/irc-server-bridge.js | 169 +- .../server/irc-server-settings.js | 26 +- 6 files changed, 12828 insertions(+), 147 deletions(-) create mode 100644 package-lock.json diff --git a/.eslintrc b/.eslintrc index 2c9849702331a..db4775c0169b0 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,4 +1,5 @@ { + "parser": "babel-eslint", "parserOptions": { "sourceType": "module", "ecmaVersion": 2017, diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000000..e4c67bf825bbf --- /dev/null +++ b/package-lock.json @@ -0,0 +1,12760 @@ +{ + "name": "Rocket.Chat", + "version": "0.61.0-develop", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.36.tgz", + "integrity": "sha512-sW77BFwJ48YvQp3Gzz5xtAUiXuYOL2aMJKDwiaY3OcvdqBFurtYfOpSa4QrNyDxmOGRFSYzUpabU2m9QrlWE7w==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.36.tgz", + "integrity": "sha512-/SGPOyifPf20iTrMN+WdlY2MbKa7/o4j7B/4IAsdOusASp2icT+Wcdjf4tjJHaXNX8Pe9bpgVxLNxhRvcf8E5w==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.36", + "@babel/template": "7.0.0-beta.36", + "@babel/types": "7.0.0-beta.36" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.36.tgz", + "integrity": "sha512-vPPcx2vsSoDbcyWr9S3nd0FM3B4hEXnt0p1oKpwa08GwK0fSRxa98MyaRGf8suk8frdQlG1P3mDrz5p/Rr3pbA==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.36" + } + }, + "@babel/template": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.36.tgz", + "integrity": "sha512-mUBi90WRyZ9iVvlWLEdeo8gn/tROyJdjKNC4W5xJTSZL+9MS89rTJSqiaJKXIkxk/YRDL/g/8snrG/O0xl33uA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.36", + "@babel/types": "7.0.0-beta.36", + "babylon": "7.0.0-beta.36", + "lodash": "4.17.4" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.36.tgz", + "integrity": "sha512-rw4YdadGwajAMMRl6a5swhQ0JCOOFyaYCfJ0AsmNBD8uBD/r4J8mux7wBaqavvFKqUKQYWOzA1Speams4YDzsQ==", + "dev": true + } + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.36.tgz", + "integrity": "sha512-OTUb6iSKVR/98dGThRJ1BiyfwbuX10BVnkz89IpaerjTPRhDfMBfLsqmzxz5MiywUOW4M0Clta0o7rSxkfcuzw==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.36", + "@babel/helper-function-name": "7.0.0-beta.36", + "@babel/types": "7.0.0-beta.36", + "babylon": "7.0.0-beta.36", + "debug": "3.1.0", + "globals": "11.3.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.36.tgz", + "integrity": "sha512-rw4YdadGwajAMMRl6a5swhQ0JCOOFyaYCfJ0AsmNBD8uBD/r4J8mux7wBaqavvFKqUKQYWOzA1Speams4YDzsQ==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.36.tgz", + "integrity": "sha512-PyAORDO9um9tfnrddXgmWN9e6Sq9qxraQIt5ynqBOSXKA5qvK1kUr+Q3nSzKFdzorsiK+oqcUnAFvEoKxv9D+Q==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@google-cloud/common": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.12.2.tgz", + "integrity": "sha1-eMNEKIxGBaKfTCiZORdZ19yBfEM=", + "requires": { + "array-uniq": "1.0.3", + "arrify": "1.0.1", + "concat-stream": "1.6.0", + "create-error-class": "3.0.2", + "duplexify": "3.5.3", + "ent": "2.2.0", + "extend": "3.0.1", + "google-auto-auth": "0.5.4", + "is": "3.2.1", + "log-driver": "1.2.5", + "methmeth": "1.1.0", + "modelo": "4.2.3", + "request": "2.83.0", + "retry-request": "1.3.2", + "split-array-stream": "1.0.3", + "stream-events": "1.0.2", + "string-format-obj": "1.1.1", + "through2": "2.0.3" + } + }, + "@google-cloud/common-grpc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@google-cloud/common-grpc/-/common-grpc-0.4.3.tgz", + "integrity": "sha1-g2iVkaEBH+5X0yqmoX/ixes6cLw=", + "requires": { + "@google-cloud/common": "0.13.6", + "dot-prop": "2.4.0", + "duplexify": "3.5.3", + "extend": "3.0.1", + "grpc": "1.8.0", + "is": "3.2.1", + "modelo": "4.2.3", + "retry-request": "3.3.1", + "through2": "2.0.3" + }, + "dependencies": { + "@google-cloud/common": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.13.6.tgz", + "integrity": "sha1-qdjhN7xCmkSrqWif5qDkMxeE+FM=", + "requires": { + "array-uniq": "1.0.3", + "arrify": "1.0.1", + "concat-stream": "1.6.0", + "create-error-class": "3.0.2", + "duplexify": "3.5.3", + "ent": "2.2.0", + "extend": "3.0.1", + "google-auto-auth": "0.7.2", + "is": "3.2.1", + "log-driver": "1.2.5", + "methmeth": "1.1.0", + "modelo": "4.2.3", + "request": "2.83.0", + "retry-request": "3.3.1", + "split-array-stream": "1.0.3", + "stream-events": "1.0.2", + "string-format-obj": "1.1.1", + "through2": "2.0.3" + } + }, + "dot-prop": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-2.4.0.tgz", + "integrity": "sha1-hI4o9/HVB0DGdHqzywdnBGK2+Jw=", + "requires": { + "is-obj": "1.0.1" + } + }, + "google-auto-auth": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.7.2.tgz", + "integrity": "sha1-v5NS1cSgiXvzH9nEkQKLdl++px4=", + "requires": { + "async": "2.6.0", + "gcp-metadata": "0.3.1", + "google-auth-library": "0.10.0", + "request": "2.83.0" + } + }, + "retry-request": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.3.1.tgz", + "integrity": "sha1-+3EnYjWmF+l1Uem+c3q1uRWR+54=", + "requires": { + "request": "2.83.0", + "through2": "2.0.3" + } + } + } + }, + "@google-cloud/language": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@google-cloud/language/-/language-0.8.0.tgz", + "integrity": "sha1-DuPsaYi5UrjZrLvpgAk/g2Y757Y=", + "requires": { + "@google-cloud/common": "0.12.2", + "arrify": "1.0.1", + "extend": "3.0.1", + "google-gax": "0.10.8", + "google-proto-files": "0.8.6", + "is": "3.2.1", + "propprop": "0.3.1", + "string-format-obj": "1.1.1" + } + }, + "@google-cloud/storage": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-1.4.0.tgz", + "integrity": "sha512-vt1NU7D12OGYPhWfwBD1Q2qFS6Suykorlp3NLaES2W9CW6sEBWLwScxElXt8nPvonYBCFt99jP4g1AqY+0hefw==", + "requires": { + "@google-cloud/common": "0.13.6", + "arrify": "1.0.1", + "async": "2.6.0", + "concat-stream": "1.6.0", + "create-error-class": "3.0.2", + "duplexify": "3.5.3", + "extend": "3.0.1", + "gcs-resumable-upload": "0.8.2", + "hash-stream-validation": "0.2.1", + "is": "3.2.1", + "mime-types": "2.1.17", + "once": "1.4.0", + "pumpify": "1.3.6", + "safe-buffer": "5.1.1", + "snakeize": "0.1.0", + "stream-events": "1.0.2", + "string-format-obj": "1.1.1", + "through2": "2.0.3" + }, + "dependencies": { + "@google-cloud/common": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.13.6.tgz", + "integrity": "sha1-qdjhN7xCmkSrqWif5qDkMxeE+FM=", + "requires": { + "array-uniq": "1.0.3", + "arrify": "1.0.1", + "concat-stream": "1.6.0", + "create-error-class": "3.0.2", + "duplexify": "3.5.3", + "ent": "2.2.0", + "extend": "3.0.1", + "google-auto-auth": "0.7.2", + "is": "3.2.1", + "log-driver": "1.2.5", + "methmeth": "1.1.0", + "modelo": "4.2.3", + "request": "2.83.0", + "retry-request": "3.3.1", + "split-array-stream": "1.0.3", + "stream-events": "1.0.2", + "string-format-obj": "1.1.1", + "through2": "2.0.3" + } + }, + "google-auto-auth": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.7.2.tgz", + "integrity": "sha1-v5NS1cSgiXvzH9nEkQKLdl++px4=", + "requires": { + "async": "2.6.0", + "gcp-metadata": "0.3.1", + "google-auth-library": "0.10.0", + "request": "2.83.0" + } + }, + "retry-request": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.3.1.tgz", + "integrity": "sha1-+3EnYjWmF+l1Uem+c3q1uRWR+54=", + "requires": { + "request": "2.83.0", + "through2": "2.0.3" + } + } + } + }, + "@google-cloud/vision": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/@google-cloud/vision/-/vision-0.11.5.tgz", + "integrity": "sha1-W9sS0ptVQsX7fbtelDLDmsrR9v4=", + "requires": { + "@google-cloud/common": "0.13.6", + "@google-cloud/common-grpc": "0.4.3", + "arrify": "1.0.1", + "async": "2.6.0", + "extend": "3.0.1", + "google-gax": "0.13.5", + "google-proto-files": "0.12.1", + "is": "3.2.1", + "prop-assign": "1.0.0", + "propprop": "0.3.1", + "rgb-hex": "1.0.0", + "string-format-obj": "1.1.1" + }, + "dependencies": { + "@google-cloud/common": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.13.6.tgz", + "integrity": "sha1-qdjhN7xCmkSrqWif5qDkMxeE+FM=", + "requires": { + "array-uniq": "1.0.3", + "arrify": "1.0.1", + "concat-stream": "1.6.0", + "create-error-class": "3.0.2", + "duplexify": "3.5.3", + "ent": "2.2.0", + "extend": "3.0.1", + "google-auto-auth": "0.7.2", + "is": "3.2.1", + "log-driver": "1.2.5", + "methmeth": "1.1.0", + "modelo": "4.2.3", + "request": "2.83.0", + "retry-request": "3.3.1", + "split-array-stream": "1.0.3", + "stream-events": "1.0.2", + "string-format-obj": "1.1.1", + "through2": "2.0.3" + } + }, + "google-auto-auth": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.7.2.tgz", + "integrity": "sha1-v5NS1cSgiXvzH9nEkQKLdl++px4=", + "requires": { + "async": "2.6.0", + "gcp-metadata": "0.3.1", + "google-auth-library": "0.10.0", + "request": "2.83.0" + } + }, + "google-gax": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-0.13.5.tgz", + "integrity": "sha1-OkjMUrfhZPcxk4836t0rc/fEk9c=", + "requires": { + "extend": "3.0.1", + "globby": "6.1.0", + "google-auto-auth": "0.5.4", + "google-proto-files": "0.13.1", + "grpc": "1.8.0", + "is-stream-ended": "0.1.3", + "lodash": "4.17.4", + "process-nextick-args": "1.0.7", + "protobufjs": "6.8.4", + "readable-stream": "2.3.3", + "through2": "2.0.3" + }, + "dependencies": { + "google-auto-auth": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.5.4.tgz", + "integrity": "sha1-HYbHko1jPnWpwasDSlJ+/M5KQLE=", + "requires": { + "async": "2.6.0", + "google-auth-library": "0.10.0", + "object-assign": "3.0.0", + "request": "2.83.0" + } + }, + "google-proto-files": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/google-proto-files/-/google-proto-files-0.13.1.tgz", + "integrity": "sha1-/PEjY30YEWEtakywMP0UUWta7Es=" + } + } + }, + "google-proto-files": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/google-proto-files/-/google-proto-files-0.12.1.tgz", + "integrity": "sha1-ZDTcfgJaDQyC5fBOYVxzfWpMQ4c=" + }, + "protobufjs": { + "version": "6.8.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.4.tgz", + "integrity": "sha1-GD+Q0cSspfazSnnq7dDYmtIfYDs=", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/base64": "1.1.2", + "@protobufjs/codegen": "2.0.4", + "@protobufjs/eventemitter": "1.1.0", + "@protobufjs/fetch": "1.1.0", + "@protobufjs/float": "1.0.2", + "@protobufjs/inquire": "1.1.0", + "@protobufjs/path": "1.1.2", + "@protobufjs/pool": "1.1.0", + "@protobufjs/utf8": "1.1.0", + "@types/long": "3.0.32", + "@types/node": "8.5.8", + "long": "3.2.0" + } + }, + "retry-request": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.3.1.tgz", + "integrity": "sha1-+3EnYjWmF+l1Uem+c3q1uRWR+54=", + "requires": { + "request": "2.83.0", + "through2": "2.0.3" + } + } + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha1-TIVzDlm5ofHzSQR9vyQpYDS7JzU=" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha1-fvN/DQEPsCitGtWXIuUG2SYoFcs=" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/inquire": "1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@types/long": { + "version": "3.0.32", + "resolved": "https://registry.npmjs.org/@types/long/-/long-3.0.32.tgz", + "integrity": "sha1-9OWvMenpsZbY5fyopeLiCqPWC2k=" + }, + "@types/node": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.8.tgz", + "integrity": "sha512-8KmlRxwbKZfjUHFIt3q8TF5S2B+/E5BaAoo/3mgc5h6FJzqxXkCK/VMetO+IRDtwtU6HUvovHMBn+XRj7SV9Qg==" + }, + "JSONStream": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "acorn": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", + "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", + "dev": true + }, + "addressparser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", + "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=" + }, + "adm-zip": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz", + "integrity": "sha1-hgbCy/HEJs6MjsABdER/1Jtur8E=" + }, + "agent-base": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=" + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha1-7D6LTp+AZPwCw6ybZfHCdb2o75I=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archiver": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", + "dev": true, + "requires": { + "archiver-utils": "1.3.0", + "async": "2.6.0", + "buffer-crc32": "0.2.1", + "glob": "7.1.2", + "lodash": "4.17.4", + "readable-stream": "2.3.3", + "tar-stream": "1.5.5", + "zip-stream": "1.2.0" + } + }, + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "dev": true, + "requires": { + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lazystream": "1.0.0", + "lodash": "4.17.4", + "normalize-path": "2.1.1", + "readable-stream": "2.3.3" + } + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } + } + }, + "arguejs": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/arguejs/-/arguejs-0.2.3.tgz", + "integrity": "sha1-tvk59f4OPNHz+T4qqSYkJL8xKvc=" + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, + "array-iterate": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.1.tgz", + "integrity": "sha1-hlv3+K851rCYLGCQKRSsdrwBCPY=", + "dev": true + }, + "array-parallel": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz", + "integrity": "sha1-j3hTCJJu1apHjEfmTRszS2wMlH0=" + }, + "array-series": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz", + "integrity": "sha1-3103v8XC7wdV4qpPkv6ufUtaly8=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "0.7.1", + "optjs": "3.2.2" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=", + "dev": true + }, + "ast-types": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.8.15.tgz", + "integrity": "sha1-ju8IJ/BN/w7IhXupJavj/qYZTlI=" + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", + "requires": { + "lodash": "4.17.4" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atlassian-crowd": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/atlassian-crowd/-/atlassian-crowd-0.5.0.tgz", + "integrity": "sha1-isdFqHg3mUkNF0H6Cc9HLn/zCTA=" + }, + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "dev": true + }, + "autolinker": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.6.0.tgz", + "integrity": "sha1-utN2t62OQV8i8QL8Dzf2QOZPHL8=" + }, + "autoprefixer": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.5.tgz", + "integrity": "sha1-BMy9DGphExttE/U9NxkmCSlS0ZI=", + "dev": true, + "requires": { + "browserslist": "2.11.1", + "caniuse-lite": "1.0.30000791", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "6.0.16", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "browserslist": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.1.tgz", + "integrity": "sha512-Gp4oJOQOby5TpOJJuUtCrGE0KSJOUYVa/I+/3eD/TRWEK8jqZuJPAK1t+VuG6jp0keudrqtxlH4MbYbmylun9g==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000791", + "electron-to-chromium": "1.3.30" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "aws-sdk": { + "version": "2.181.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.181.0.tgz", + "integrity": "sha1-Z+FjCId2FdypujhS/1zKJMd/nK4=", + "requires": { + "buffer": "4.9.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "events": "1.1.1", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.1.0", + "xml2js": "0.4.17", + "xmlbuilder": "4.2.1" + }, + "dependencies": { + "xml2js": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", + "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", + "requires": { + "sax": "1.2.1", + "xmlbuilder": "4.2.1" + } + }, + "xmlbuilder": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", + "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", + "requires": { + "lodash": "4.17.4" + } + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.9.1.tgz", + "integrity": "sha1-SNRx7r9N5GngqUL+RW3MlLGL6A0=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.4.0", + "lodash": "4.17.4", + "minimatch": "2.0.10", + "path-exists": "1.0.0", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "shebang-regex": "1.0.0", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-eslint": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.1.tgz", + "integrity": "sha512-RzdVOyWKQRUnLXhwLk+eKb4oyW+BykZSkpYwFhM4tnfzAG5OWfvG0w/uyzMp5XKEU0jN82+JefHr39bG2+KhRQ==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.36", + "@babel/traverse": "7.0.0-beta.36", + "@babel/types": "7.0.0-beta.36", + "babylon": "7.0.0-beta.36", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.36.tgz", + "integrity": "sha512-rw4YdadGwajAMMRl6a5swhQ0JCOOFyaYCfJ0AsmNBD8uBD/r4J8mux7wBaqavvFKqUKQYWOzA1Speams4YDzsQ==", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", + "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "esutils": "2.0.2" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-mocha-es6-compiler": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/babel-mocha-es6-compiler/-/babel-mocha-es6-compiler-0.1.0.tgz", + "integrity": "sha1-QMnkBoCvRhWP7usntJQUtrgOxDg=", + "dev": true, + "requires": { + "babel-core": "6.9.1", + "babel-plugin-add-module-exports": "0.2.1", + "babel-preset-es2015": "6.3.13", + "babel-preset-react": "6.3.13", + "babel-preset-stage-0": "6.3.13" + } + }, + "babel-plugin-add-module-exports": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz", + "integrity": "sha1-mumh9KjcZ/DN7E9K7aHkOl/2XiU=", + "dev": true + }, + "babel-plugin-array-includes": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/babel-plugin-array-includes/-/babel-plugin-array-includes-2.0.3.tgz", + "integrity": "sha1-z1RS6Bx7gD+3lZ8QRayI4uwo/3Y=", + "dev": true + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", + "dev": true + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", + "dev": true + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", + "dev": true + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", + "dev": true + }, + "babel-plugin-syntax-do-expressions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", + "dev": true + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", + "dev": true + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true + }, + "babel-plugin-syntax-function-bind": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", + "dev": true + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "dev": true, + "requires": { + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "dev": true, + "requires": { + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-do-expressions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", + "dev": true, + "requires": { + "babel-plugin-syntax-do-expressions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "dev": true, + "requires": { + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-function-bind": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", + "dev": true, + "requires": { + "babel-plugin-syntax-function-bind": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "6.26.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz", + "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.5.3", + "regenerator-runtime": "0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-es2015": { + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.3.13.tgz", + "integrity": "sha1-l9zn7ykuGMubK3VF2AxZPCjZUX8=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0" + } + }, + "babel-preset-react": { + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.3.13.tgz", + "integrity": "sha1-E9VeBqZfqqoHw5v2Op2DbgMhFvo=", + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-plugin-transform-react-display-name": "6.25.0", + "babel-plugin-transform-react-jsx": "6.24.1", + "babel-plugin-transform-react-jsx-source": "6.22.0" + } + }, + "babel-preset-stage-0": { + "version": "6.3.13", + "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.3.13.tgz", + "integrity": "sha1-eKN8VvCzmI8qeZMtywzrj/N3sNE=", + "dev": true, + "requires": { + "babel-plugin-transform-do-expressions": "6.22.0", + "babel-plugin-transform-function-bind": "6.22.0", + "babel-preset-stage-1": "6.24.1" + } + }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "dev": true, + "requires": { + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-preset-stage-2": "6.24.1" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.26.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.3", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + }, + "dependencies": { + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "backoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", + "requires": { + "precond": "0.2.3" + } + }, + "bad-words": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/bad-words/-/bad-words-1.3.1.tgz", + "integrity": "sha1-YD3VpBLnItb/vGtqnIiKNzQTv4I=", + "requires": { + "badwords-list": "1.0.0" + } + }, + "badwords-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/badwords-list/-/badwords-list-1.0.0.tgz", + "integrity": "sha1-XphW2/E0gqKVw7CzBK+51M/FxXk=" + }, + "bail": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.2.tgz", + "integrity": "sha1-99bBcxYwqfnw1NNe0fli4gdKF2Q=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base32.js": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.0.1.tgz", + "integrity": "sha1-0EVzalex9sE58MffQlGKhOkbsro=" + }, + "base62": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz", + "integrity": "sha1-e0F0wvlESXU7EcJlHAg9qEGnsIQ=" + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==" + }, + "base64url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", + "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" + }, + "bcrypt": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz", + "integrity": "sha512-pRyDdo73C8Nim3jwFJ7DWe3TZCgwDfWZ6nHS5LSdU77kWbj1frruvdndP02AOavtD4y8v6Fp2dolbHgp4SDrfg==", + "requires": { + "nan": "2.6.2", + "node-pre-gyp": "0.6.36" + }, + "dependencies": { + "nan": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", + "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bintrees": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", + "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" + }, + "bl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "requires": { + "readable-stream": "2.3.3" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "2.0.3" + } + }, + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "requires": { + "caniuse-db": "1.0.30000791", + "electron-to-chromium": "1.3.30" + } + }, + "bson": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.5.5.tgz", + "integrity": "sha1-HWcl1ADw+/AnG/a6/I+hEmwpmDs=" + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "buffer-crc32": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz", + "integrity": "sha1-vj5TgvwCttYySVasGvmKqYsIU0w=" + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "bugsnag": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/bugsnag/-/bugsnag-1.8.0.tgz", + "integrity": "sha1-5BKdm6KaxRQSANGG/4wK/vdDN8c=", + "requires": { + "promise": "7.3.1", + "request": "2.83.0", + "stack-trace": "0.0.9" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "bunyan": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz", + "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=", + "requires": { + "dtrace-provider": "0.8.6", + "moment": "2.20.1", + "mv": "2.1.1", + "safe-json-stringify": "1.0.4" + } + }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "3.2.0" + } + }, + "bytes": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-0.2.0.tgz", + "integrity": "sha1-qtM+wU49wsp06OfUUfm6BTrU96A=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "2.3.2", + "upper-case": "1.1.3" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "caniuse-db": { + "version": "1.0.30000791", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000791.tgz", + "integrity": "sha1-Bnh/VsrvQwChfjXRN0RxI731Nvk=" + }, + "caniuse-lite": { + "version": "1.0.30000791", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000791.tgz", + "integrity": "sha1-jjV0Xv1IOj4ju301CZAybSMZ/BY=", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + }, + "cas": { + "version": "https://github.com/kcbanner/node-cas/tarball/fcd27dad333223b3b75a048bce27973fb3ca0f62", + "integrity": "sha1-AL8m1JYV/7kMEdlJ0sKtJ18YXg4=", + "requires": { + "cheerio": "0.19.0" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "ccount": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.2.tgz", + "integrity": "sha1-U7ai+BW7d7nChx97mnLDol8djok=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.5" + } + }, + "chai-as-promised": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-6.0.0.tgz", + "integrity": "sha1-GgKkM6byTa+sY7nJb6FoTbGqjaY=", + "dev": true, + "requires": { + "check-error": "1.0.2" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "character-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.1.tgz", + "integrity": "sha1-92hxvl72bdt/j440eOzDdMJ9bco=", + "dev": true + }, + "character-entities-html4": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.1.tgz", + "integrity": "sha1-NZoqSg9+KdPcKsmb2+Ie45Q46lA=", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", + "integrity": "sha1-9Ad53xoQGHK7UQo9KV4fzPFHIC8=", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz", + "integrity": "sha1-lCg191Dk7GGjCOYMLvjMEBEgLvw=", + "dev": true + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "cheerio": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz", + "integrity": "sha1-dy5wFfLuKZZQltcepBdbdas1SSU=", + "requires": { + "css-select": "1.0.0", + "dom-serializer": "0.1.0", + "entities": "1.1.1", + "htmlparser2": "3.8.3", + "lodash": "3.10.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "child-process-debug": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/child-process-debug/-/child-process-debug-0.0.7.tgz", + "integrity": "sha1-VOEfuBw7b5Spa2MfrKk+0a9/itA=", + "dev": true + }, + "chimp": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/chimp/-/chimp-0.51.0.tgz", + "integrity": "sha1-RFr6LHsrtJlaUXWYRu9e4mlfCh0=", + "dev": true, + "requires": { + "async": "0.9.2", + "babel-core": "6.9.1", + "babel-plugin-transform-runtime": "6.23.0", + "babel-polyfill": "6.26.0", + "babel-preset-es2015": "6.3.13", + "babel-preset-stage-2": "6.24.1", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "bluebird": "3.5.1", + "chai": "4.1.2", + "chai-as-promised": "6.0.0", + "child-process-debug": "0.0.7", + "chokidar": "1.6.1", + "chromedriver": "2.34.1", + "colors": "1.1.2", + "commander": "2.13.0", + "cucumber": "github:xolvio/cucumber-js#cf953cb5b5de30dbcc279f59e4ebff3aa040071c", + "deep-extend": "0.4.2", + "exit": "0.1.2", + "fibers": "1.0.15", + "freeport": "1.0.5", + "fs-extra": "1.0.0", + "glob": "github:lucetius/node-glob#51c7ca6e69bfbd17db5f1ea710e3f2a7a457d9ce", + "hapi": "8.8.0", + "jasmine": "2.8.0", + "loglevel": "1.4.1", + "minimist": "1.2.0", + "mocha": "4.1.0", + "phantomjs-prebuilt": "2.1.15", + "progress": "1.1.8", + "request": "2.83.0", + "requestretry": "1.5.0", + "saucelabs": "1.4.0", + "selenium-standalone": "6.12.0", + "underscore": "1.8.3", + "xolvio-ddp": "0.12.3", + "xolvio-jasmine-expect": "1.1.0", + "xolvio-sync-webdriverio": "9.0.1" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "cucumber": { + "version": "github:xolvio/cucumber-js#cf953cb5b5de30dbcc279f59e4ebff3aa040071c", + "dev": true, + "requires": { + "camel-case": "3.0.0", + "cli-table": "0.3.1", + "co": "4.6.0", + "colors": "1.1.2", + "commander": "2.13.0", + "duration": "0.2.0", + "fibers": "1.0.15", + "figures": "1.7.0", + "gherkin": "4.0.0", + "glob": "github:lucetius/node-glob#51c7ca6e69bfbd17db5f1ea710e3f2a7a457d9ce", + "is-generator": "1.0.3", + "lodash": "4.17.4", + "meteor-promise": "0.8.6", + "stack-chain": "1.3.7", + "stacktrace-js": "1.3.1" + } + }, + "glob": { + "version": "github:lucetius/node-glob#51c7ca6e69bfbd17db5f1ea710e3f2a7a457d9ce", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.0", + "path-is-absolute": "1.0.1" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "once": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.0.tgz", + "integrity": "sha1-FRr4a/wfCMS58H0GqyUP/L61ZYE=", + "dev": true + } + } + }, + "chokidar": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz", + "integrity": "sha1-L0RHq16W5Q+z14n9kNTHLg5McMI=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "chromedriver": { + "version": "2.34.1", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-2.34.1.tgz", + "integrity": "sha1-TO/xse94X7Qb11ApFn6UtQvXeEQ=", + "dev": true, + "requires": { + "del": "3.0.0", + "extract-zip": "1.6.6", + "kew": "0.7.0", + "mkdirp": "0.5.1", + "request": "2.83.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "dev": true, + "requires": { + "colors": "1.0.3" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "clipboard": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz", + "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=", + "requires": { + "good-listener": "1.2.2", + "select": "1.1.2", + "tiny-emitter": "2.0.2" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "clone-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.0.tgz", + "integrity": "sha1-6uCiQT9VwJQvgYwin+/OhF1/Oxw=", + "dev": true, + "requires": { + "is-regexp": "1.0.0", + "is-supported-regexp-flag": "1.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "codemirror": { + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.33.0.tgz", + "integrity": "sha1-RirZpv6NOLVBqVNqOZfh75O0DGo=" + }, + "coffeescript": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.7.tgz", + "integrity": "sha1-5X7kxIZ89/YGv8Sg8tVQwJgd3Sc=" + }, + "collapse-white-space": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", + "integrity": "sha1-S5BvZw5aljqHt2sOFolkM0G2Ajw=", + "dev": true + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha1-aWS8pnaF33wfFDDFhPB9dZeIW5w=" + }, + "compare-func": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", + "integrity": "sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg=", + "dev": true, + "requires": { + "array-ify": "1.0.0", + "dot-prop": "3.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", + "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "dev": true, + "requires": { + "is-obj": "1.0.1" + } + } + } + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.1", + "crc32-stream": "2.0.0", + "normalize-path": "2.1.1", + "readable-stream": "2.3.3" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "configstore": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", + "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.1.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "connect": { + "version": "2.7.10", + "resolved": "https://registry.npmjs.org/connect/-/connect-2.7.10.tgz", + "integrity": "sha1-oKxZRk1lJAedsCyXFRx5XBtN7mQ=", + "requires": { + "buffer-crc32": "0.2.1", + "bytes": "0.2.0", + "cookie": "0.0.5", + "cookie-signature": "1.0.1", + "debug": "2.6.9", + "formidable": "1.0.14", + "fresh": "0.1.0", + "pause": "0.0.1", + "qs": "0.6.5", + "send": "0.1.0" + }, + "dependencies": { + "qs": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.5.tgz", + "integrity": "sha1-KUsmjksNQlD23eGbO4s0k13/FO8=" + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "conventional-changelog": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-1.1.7.tgz", + "integrity": "sha1-kVGmKx2O2y2CcR2r9bfPcQQfgrE=", + "dev": true, + "requires": { + "conventional-changelog-angular": "1.6.0", + "conventional-changelog-atom": "0.1.2", + "conventional-changelog-codemirror": "0.2.1", + "conventional-changelog-core": "1.9.5", + "conventional-changelog-ember": "0.2.10", + "conventional-changelog-eslint": "0.2.1", + "conventional-changelog-express": "0.2.1", + "conventional-changelog-jquery": "0.1.0", + "conventional-changelog-jscs": "0.1.0", + "conventional-changelog-jshint": "0.2.1" + } + }, + "conventional-changelog-angular": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-1.6.0.tgz", + "integrity": "sha1-CiagcfLJ/PzyuGugz79uYwG3W/o=", + "dev": true, + "requires": { + "compare-func": "1.3.2", + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-atom": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-0.1.2.tgz", + "integrity": "sha1-Ella1SZ6aTfDTPkAKBscZRmKTGM=", + "dev": true, + "requires": { + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-cli": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/conventional-changelog-cli/-/conventional-changelog-cli-1.3.5.tgz", + "integrity": "sha1-RsUUliFrdAZYiIPe+m+sWJ6bsx4=", + "dev": true, + "requires": { + "add-stream": "1.0.0", + "conventional-changelog": "1.1.7", + "lodash": "4.17.4", + "meow": "3.7.0", + "tempfile": "1.1.1" + } + }, + "conventional-changelog-codemirror": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-0.2.1.tgz", + "integrity": "sha1-KZpPcUe681DmyBWPxUlUopHFzAk=", + "dev": true, + "requires": { + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-core": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-1.9.5.tgz", + "integrity": "sha1-XbdWba18DLddr0f7spdve/mSjB0=", + "dev": true, + "requires": { + "conventional-changelog-writer": "2.0.3", + "conventional-commits-parser": "2.1.0", + "dateformat": "1.0.12", + "get-pkg-repo": "1.4.0", + "git-raw-commits": "1.3.0", + "git-remote-origin-url": "2.0.0", + "git-semver-tags": "1.2.3", + "lodash": "4.17.4", + "normalize-package-data": "2.4.0", + "q": "1.5.1", + "read-pkg": "1.1.0", + "read-pkg-up": "1.0.1", + "through2": "2.0.3" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-ember": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-0.2.10.tgz", + "integrity": "sha1-3NbkzcLmwrWGU89NLLFlamBCGSk=", + "dev": true, + "requires": { + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-eslint": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-0.2.1.tgz", + "integrity": "sha1-LCoRvrIW+AZJunKDQYApO2h8BmI=", + "dev": true, + "requires": { + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-express": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-0.2.1.tgz", + "integrity": "sha1-g42eHmyQmXA7FQucGaoteBdCvWw=", + "dev": true, + "requires": { + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-jquery": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-0.1.0.tgz", + "integrity": "sha1-Agg5cWLjhGmG5xJztsecW1+A9RA=", + "dev": true, + "requires": { + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-jscs": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jscs/-/conventional-changelog-jscs-0.1.0.tgz", + "integrity": "sha1-BHnrRDzH1yxYvwvPDvHURKkvDlw=", + "dev": true, + "requires": { + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-jshint": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-0.2.1.tgz", + "integrity": "sha1-hhObs6yZiZ8rF36WF+CbN9mbzzo=", + "dev": true, + "requires": { + "compare-func": "1.3.2", + "q": "1.5.1" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, + "conventional-changelog-writer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-2.0.3.tgz", + "integrity": "sha1-BzsMOfHMj8D9mxVm6Tgz9RSJyBw=", + "dev": true, + "requires": { + "compare-func": "1.3.2", + "conventional-commits-filter": "1.1.1", + "dateformat": "1.0.12", + "handlebars": "4.0.11", + "json-stringify-safe": "5.0.1", + "lodash": "4.17.4", + "meow": "3.7.0", + "semver": "5.4.1", + "split": "1.0.1", + "through2": "2.0.3" + } + }, + "conventional-commits-filter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-1.1.1.tgz", + "integrity": "sha1-chcjGcDIgyigFbMGhrVVJ7Ol5Uo=", + "dev": true, + "requires": { + "is-subset": "0.1.1", + "modify-values": "1.0.0" + } + }, + "conventional-commits-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-2.1.0.tgz", + "integrity": "sha1-m0t8kRJL8qGposwccnYNOCy7sik=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "is-text-path": "1.0.1", + "lodash": "4.17.4", + "meow": "3.7.0", + "split2": "2.2.0", + "through2": "2.0.3", + "trim-off-newlines": "1.0.1" + } + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "cookie": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.0.5.tgz", + "integrity": "sha1-+az521frdWjJ/MWWJWt7si4wfIE=" + }, + "cookie-signature": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.1.tgz", + "integrity": "sha1-ROByFIrwHm6OJK+/EmkNaK5pjss=" + }, + "cookiejar": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.1.tgz", + "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o=", + "dev": true + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-3.1.0.tgz", + "integrity": "sha512-zedsBhLSbPBms+kE7AH4vHg6JsKDz6epSv2/+5XHs8ILHlgDciSJfSWf8sX9aQ52Jb7KI7VswUTsLpR/G0cr2Q==", + "dev": true, + "requires": { + "is-directory": "0.3.1", + "js-yaml": "3.10.0", + "parse-json": "3.0.0", + "require-from-string": "2.0.1" + }, + "dependencies": { + "parse-json": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-3.0.0.tgz", + "integrity": "sha1-+m9HsY4jgm6tMvJj50TQ4ehH+xM=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + } + } + }, + "crc": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.5.0.tgz", + "integrity": "sha1-mLi6fUiWZbo5efWbITgTdBAaGWQ=", + "dev": true + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "dev": true, + "requires": { + "crc": "3.5.0", + "readable-stream": "2.3.3" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.9" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "requires": { + "lru-cache": "4.1.1", + "which": "1.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + } + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + }, + "css": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.3.1", + "urix": "0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "2.2.1" + } + }, + "css-select": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz", + "integrity": "sha1-sRIcpRhI3SZOIkTQWM7iVN7rRLA=", + "requires": { + "boolbase": "1.0.0", + "css-what": "1.0.0", + "domutils": "1.4.3", + "nth-check": "1.0.1" + } + }, + "css-value": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", + "dev": true + }, + "css-what": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz", + "integrity": "sha1-18wt9FGAZm+Z0rFEYmOUaeAPc2w=" + }, + "csv-parse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-1.2.0.tgz", + "integrity": "sha1-BHtzhoq5qFdG6IX2N/ntD7ZFpCU=" + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=" + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "dev": true, + "requires": { + "es5-ext": "0.10.37" + } + }, + "dargs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", + "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "ddp-ejson": { + "version": "0.8.1-3", + "resolved": "https://registry.npmjs.org/ddp-ejson/-/ddp-ejson-0.8.1-3.tgz", + "integrity": "sha1-6dZ0Zqt4m9dOfZcHSjbiQGkO7sI=", + "dev": true, + "requires": { + "ddp-underscore-patched": "0.8.1-2" + } + }, + "ddp-underscore-patched": { + "version": "0.8.1-2", + "resolved": "https://registry.npmjs.org/ddp-underscore-patched/-/ddp-underscore-patched-0.8.1-2.tgz", + "integrity": "sha1-ZaQU6fIuxagqoWOG40NmtI/Ozx0=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "1.2.0", + "map-obj": "1.0.1" + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", + "dev": true, + "requires": { + "type-detect": "4.0.5" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "deepmerge": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.0.1.tgz", + "integrity": "sha1-JcHCTxEPuRT4AAG5JSZN138/QxI=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "6.1.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "p-map": "1.2.0", + "pify": "3.0.0", + "rimraf": "2.6.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha1-tmtxwxWFIuirV0T3INjKDCr1kWY=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "deprecate": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/deprecate/-/deprecate-0.1.0.tgz", + "integrity": "sha1-xJBYYS3GyOUUXq/kg5uMLH0EHBQ=" + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.14", + "streamsearch": "0.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha1-qoVnpu7QPFMfyJ0/cRzQ5SWd7HU=", + "dev": true + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + } + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.4.3.tgz", + "integrity": "sha1-CGVRN5bGswYDGFDhdVFrr4C3Km8=", + "requires": { + "domelementtype": "1.3.0" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "1.0.1" + } + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + }, + "dtrace-provider": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.6.tgz", + "integrity": "sha1-QooiOv4DQl0s1tY0f99AxmkDVj0=", + "optional": true, + "requires": { + "nan": "2.8.0" + } + }, + "duplexify": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "integrity": "sha1-i1gYgA35L9ASWyeriWSRkShYJD4=", + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + } + }, + "duration": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.0.tgz", + "integrity": "sha1-X5xN+q//ZV3phhEu/iXFl43YUUY=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.37" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", + "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", + "requires": { + "base64url": "2.0.0", + "safe-buffer": "5.1.1" + } + }, + "ejs": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", + "dev": true + }, + "electron-releases": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/electron-releases/-/electron-releases-2.1.0.tgz", + "integrity": "sha512-cyKFD1bTE/UgULXfaueIN1k5EPFzs+FRc/rvCY5tIynefAPqopQEgjr0EzY+U3Dqrk/G4m9tXSPuZ77v6dL/Rw==" + }, + "electron-to-chromium": { + "version": "1.3.30", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz", + "integrity": "sha512-zx1Prv7kYLfc4OA60FhxGbSo4qrEjgSzpo1/37i7l9ltXPYOoQBtjQxY9KmsgfHnBxHlBGXwLlsbt/gub1w5lw==", + "requires": { + "electron-releases": "2.1.0" + } + }, + "emailreplyparser": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/emailreplyparser/-/emailreplyparser-0.0.5.tgz", + "integrity": "sha1-BpYswKRCFnWbo7mOOyV3wM4w/Aw=" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "requires": { + "once": "1.4.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + }, + "errno": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", + "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", + "optional": true, + "requires": { + "prr": "1.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "error-stack-parser": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-1.3.6.tgz", + "integrity": "sha1-4Oc7k+QXE40c18C3RrGkoUhUwpI=", + "dev": true, + "requires": { + "stackframe": "0.3.1" + } + }, + "es3ify": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/es3ify/-/es3ify-0.1.4.tgz", + "integrity": "sha1-rZ+l3xrjTz8x4SEbWBiy1RB439E=", + "requires": { + "esprima-fb": "3001.1.0-dev-harmony-fb", + "jstransform": "3.0.0", + "through": "2.3.8" + } + }, + "es5-ext": { + "version": "0.10.37", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", + "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-symbol": "3.1.1" + }, + "dependencies": { + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.37" + } + } + } + }, + "es6-promise": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz", + "integrity": "sha1-eILzCt3lskDM+n99eMVIMwlRrkI=", + "dev": true + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + }, + "dependencies": { + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.37" + } + } + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "eslint": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.15.0.tgz", + "integrity": "sha512-zEO/Z1ZUxIQ+MhDVKkVTUYpIPDTEJLXGMrkID+5v1NeQHtCz6FZikWuFRgxE1Q/RV2V4zVl1u3xmpPADHhMZ6A==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.3.0", + "concat-stream": "1.6.0", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.2", + "esquery": "1.0.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.1.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.0.1", + "js-yaml": "3.10.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.1.0.tgz", + "integrity": "sha512-uEuWt9mqTlPDwSqi+sHjD4nWU/1N+q0fiWI9T1mZpD2UENqX20CFD5T/ziLZvztPaBKl7ZylUi1q6Qfm7E2CiQ==", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", + "dev": true + }, + "esmangle-evaluator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esmangle-evaluator/-/esmangle-evaluator-1.0.1.tgz", + "integrity": "sha1-Yg2GbvSGGzMR91dm1SqFcrs8YzY=" + }, + "espree": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", + "integrity": "sha1-dWrai5eenc/NswqtjRqTBKkF4co=", + "dev": true, + "requires": { + "acorn": "5.3.0", + "acorn-jsx": "3.0.1" + }, + "dependencies": { + "acorn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", + "integrity": "sha1-dEbTlFnFT7SagObuZHgUm5QOyCI=", + "dev": true + } + } + }, + "esprima-fb": { + "version": "3001.1.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz", + "integrity": "sha1-t303q8046gt3Qmu4vCkizmtCZBE=" + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=" + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "execall": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz", + "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=", + "dev": true, + "requires": { + "clone-regexp": "1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha1-PQJqIbf5W1cmOH1CAKwWDTcsO0g=", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extract-zip": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz", + "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "debug": "2.6.9", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "falafel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz", + "integrity": "sha1-wY0k71CRF0pJfzGM0ksCaiXN2rQ=", + "requires": { + "acorn": "1.2.2", + "foreach": "2.0.5", + "isarray": "0.0.1", + "object-keys": "1.0.11" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "faye-websocket": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.4.tgz", + "integrity": "sha1-iFk0x57/sECVSeDAo4Ae0XpAza0=", + "dev": true, + "requires": { + "websocket-driver": "0.7.0" + } + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "fg-lodash": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fg-lodash/-/fg-lodash-0.0.2.tgz", + "integrity": "sha1-mINSU39CfaavIiEpu2OsyknmL6M=", + "dev": true, + "requires": { + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "fibers": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/fibers/-/fibers-1.0.15.tgz", + "integrity": "sha1-IvA5yPGLhWGQ+75N7PBWFUwerpw=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "file-type": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-7.4.0.tgz", + "integrity": "sha1-KnyU9ioAMBULt9m2xwz6HT51nIY=" + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "filesize": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.5.11.tgz", + "integrity": "sha1-GRkyZ0lDO7PPdzaL0VjKq8wZ6e4=" + }, + "fill-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "dev": true, + "requires": { + "is-object": "1.0.1", + "merge-descriptors": "1.0.1" + } + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + }, + "dependencies": { + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "flushwritable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flushwritable/-/flushwritable-1.0.0.tgz", + "integrity": "sha1-PjKNj95BKtR+c44751C00pAENJg=" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "formidable": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz", + "integrity": "sha1-Kz9MQRy7X91pXESEPiojUUpDIxo=" + }, + "freeport": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/freeport/-/freeport-1.0.5.tgz", + "integrity": "sha1-JV6KuEFwwzuoXZkOghrl9KGpvF0=", + "dev": true + }, + "fresh": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.1.0.tgz", + "integrity": "sha1-A+SwF4Qk5MLV0ZpU2IFM3JeTSFA=" + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + } + } + }, + "gaze": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "dev": true, + "requires": { + "globule": "1.2.0" + } + }, + "gcp-metadata": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.3.1.tgz", + "integrity": "sha512-5kJPX/RXuqoLmHiOOgkSDk/LI0QaXpEvZ3pvQP4ifjGGDKZKVSOjL/GcDjXA5kLxppFCOjmmsu0Uoop9d1upaQ==", + "requires": { + "extend": "3.0.1", + "retry-request": "3.3.1" + }, + "dependencies": { + "retry-request": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.3.1.tgz", + "integrity": "sha1-+3EnYjWmF+l1Uem+c3q1uRWR+54=", + "requires": { + "request": "2.83.0", + "through2": "2.0.3" + } + } + } + }, + "gcs-resumable-upload": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-0.8.2.tgz", + "integrity": "sha512-PBl1OFABYxubxfYPh000I0+JLbQzBRtNqxzgxYboIQk2tdw7BvjJ2dVukk3YH4QM6GiUwqItyNqWBuxjLH8GhA==", + "requires": { + "buffer-equal": "1.0.0", + "configstore": "3.1.1", + "google-auto-auth": "0.7.2", + "pumpify": "1.3.6", + "request": "2.83.0", + "stream-events": "1.0.2", + "through2": "2.0.3" + }, + "dependencies": { + "google-auto-auth": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.7.2.tgz", + "integrity": "sha1-v5NS1cSgiXvzH9nEkQKLdl++px4=", + "requires": { + "async": "2.6.0", + "gcp-metadata": "0.3.1", + "google-auth-library": "0.10.0", + "request": "2.83.0" + } + } + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "requires": { + "is-property": "1.0.2" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-pkg-repo": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", + "integrity": "sha1-xztInAbYDMVTbCyFP54FIyBWly0=", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "meow": "3.7.0", + "normalize-package-data": "2.4.0", + "parse-github-repo-url": "1.4.1", + "through2": "2.0.3" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "gherkin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gherkin/-/gherkin-4.0.0.tgz", + "integrity": "sha1-edzgTRIj6kO0hip2vlzo+JwSwyw=", + "dev": true + }, + "git-raw-commits": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-1.3.0.tgz", + "integrity": "sha1-C8hZbpDV/+c29/VUa9LRL3OrqsY=", + "dev": true, + "requires": { + "dargs": "4.1.0", + "lodash.template": "4.4.0", + "meow": "3.7.0", + "split2": "2.2.0", + "through2": "2.0.3" + } + }, + "git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", + "dev": true, + "requires": { + "gitconfiglocal": "1.0.0", + "pify": "2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "git-semver-tags": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-1.2.3.tgz", + "integrity": "sha1-GItFOIK/nXojr9Mbq6U32rc4jV0=", + "dev": true, + "requires": { + "meow": "3.7.0", + "semver": "5.4.1" + } + }, + "gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", + "dev": true, + "requires": { + "ini": "1.3.5" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", + "dev": true + }, + "globule": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.4", + "minimatch": "3.0.4" + } + }, + "gm": { + "version": "1.23.1", + "resolved": "https://registry.npmjs.org/gm/-/gm-1.23.1.tgz", + "integrity": "sha1-Lt7rlYCE0PjqeYjl2ZWxx9/BR3c=", + "requires": { + "array-parallel": "0.1.3", + "array-series": "0.1.5", + "cross-spawn": "4.0.2", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "gonzales-pe": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.2.3.tgz", + "integrity": "sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw==", + "dev": true, + "requires": { + "minimist": "1.1.3" + }, + "dependencies": { + "minimist": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz", + "integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=", + "dev": true + } + } + }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "requires": { + "delegate": "3.2.0" + } + }, + "google-auth-library": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-0.10.0.tgz", + "integrity": "sha1-bhW6vuhf0d0U2NEoopW2g41SE24=", + "requires": { + "gtoken": "1.2.3", + "jws": "3.1.4", + "lodash.noop": "3.0.1", + "request": "2.83.0" + } + }, + "google-auto-auth": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.5.4.tgz", + "integrity": "sha1-HYbHko1jPnWpwasDSlJ+/M5KQLE=", + "requires": { + "async": "2.6.0", + "google-auth-library": "0.10.0", + "object-assign": "3.0.0", + "request": "2.83.0" + } + }, + "google-gax": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-0.10.8.tgz", + "integrity": "sha1-IKas3I/PAdccHJkLheZldh423fA=", + "requires": { + "extend": "3.0.1", + "google-auto-auth": "0.5.4", + "google-proto-files": "0.9.1", + "grpc": "1.8.0", + "lodash": "4.17.4", + "process-nextick-args": "1.0.7", + "readable-stream": "2.3.3" + }, + "dependencies": { + "google-proto-files": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/google-proto-files/-/google-proto-files-0.9.1.tgz", + "integrity": "sha1-x2DHkFm/Yro6xW4dG6e41FYIA74=" + } + } + }, + "google-p12-pem": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-0.1.2.tgz", + "integrity": "sha1-M8RqsCGqc0+gMys5YKmj/8svMXc=", + "requires": { + "node-forge": "0.7.1" + } + }, + "google-proto-files": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/google-proto-files/-/google-proto-files-0.8.6.tgz", + "integrity": "sha1-p8jdzNIXlpDScLDr/EKZTVbaDuY=" + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "gridfs-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/gridfs-stream/-/gridfs-stream-1.1.1.tgz", + "integrity": "sha1-PdOhAOwgIaGBKC9utGcJY2B034k=", + "requires": { + "flushwritable": "1.0.0" + } + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha1-GSa6kM8+3+KttJJ/WIC8IsZseQ8=", + "dev": true + }, + "grpc": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.8.0.tgz", + "integrity": "sha512-AwVQiyMdNv09O4kwec3z52HwkPuo1i61Uk1oENWM9CDeLAUiixQLMpXDIJL31MmZdAuKnAYds/naFEXzprbgHg==", + "requires": { + "arguejs": "0.2.3", + "lodash": "4.17.4", + "nan": "2.8.0", + "node-pre-gyp": "0.6.39", + "protobufjs": "5.0.2" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node-pre-gyp": { + "version": "0.6.39", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz", + "integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==", + "requires": { + "detect-libc": "1.0.3", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.2", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.4.1", + "tar": "2.2.1", + "tar-pack": "3.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + }, + "rc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz", + "integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=", + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", + "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", + "requires": { + "debug": "2.6.9", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } + }, + "gtoken": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-1.2.3.tgz", + "integrity": "sha512-wQAJflfoqSgMWrSBk9Fg86q+sd6s7y6uJhIvvIPz++RElGlMtEqsdAR2oWwZ/WTEtp7P9xFbJRrT976oRgzJ/w==", + "requires": { + "google-p12-pem": "0.1.2", + "jws": "3.1.4", + "mime": "1.6.0", + "request": "2.83.0" + } + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, + "hapi": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/hapi/-/hapi-8.8.0.tgz", + "integrity": "sha1-h+N6Bum0meiXkOLcERqpZotuYX8=", + "dev": true, + "requires": { + "accept": "1.0.0", + "ammo": "1.0.0", + "boom": "2.7.2", + "call": "2.0.1", + "catbox": "4.3.0", + "catbox-memory": "1.1.1", + "cryptiles": "2.0.4", + "h2o2": "4.0.1", + "heavy": "3.0.0", + "hoek": "2.14.0", + "inert": "2.1.5", + "iron": "2.1.2", + "items": "1.1.0", + "joi": "6.4.1", + "kilt": "1.1.1", + "mimos": "2.0.2", + "peekaboo": "1.0.0", + "qs": "4.0.0", + "shot": "1.5.3", + "statehood": "2.1.1", + "subtext": "1.1.1", + "topo": "1.0.2", + "vision": "2.0.1" + }, + "dependencies": { + "accept": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/accept/-/accept-1.0.0.tgz", + "integrity": "sha1-g++IOWi4WkDFARYEKCoiD/AeYq0=", + "dev": true, + "requires": { + "boom": "2.7.2", + "hoek": "2.14.0" + } + }, + "ammo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ammo/-/ammo-1.0.0.tgz", + "integrity": "sha1-4FlIG/aAhzj66G1GT3L6DBLWeoU=", + "dev": true, + "requires": { + "boom": "2.7.2", + "hoek": "2.14.0" + } + }, + "boom": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.7.2.tgz", + "integrity": "sha1-2tYo2Jf3/S4yzIIZfxMweXHPg1Q=", + "dev": true, + "requires": { + "hoek": "2.14.0" + } + }, + "call": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/call/-/call-2.0.1.tgz", + "integrity": "sha1-SbQnCZQ96JoyJYqpEbWHUeI3eg4=", + "dev": true, + "requires": { + "boom": "2.7.2", + "hoek": "2.14.0" + } + }, + "catbox": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/catbox/-/catbox-4.3.0.tgz", + "integrity": "sha1-IiN3vWfxKRrA4l0AAC0GWp3385o=", + "dev": true, + "requires": { + "boom": "2.7.2", + "hoek": "2.14.0", + "joi": "6.4.1" + } + }, + "catbox-memory": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/catbox-memory/-/catbox-memory-1.1.1.tgz", + "integrity": "sha1-QqUvgLye+nJmAeltQBYDNhJIGig=", + "dev": true, + "requires": { + "hoek": "2.14.0" + } + }, + "cryptiles": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.4.tgz", + "integrity": "sha1-CeoXdbnhx95+YKmdQqtvCM4aEoU=", + "dev": true, + "requires": { + "boom": "2.7.2" + } + }, + "h2o2": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/h2o2/-/h2o2-4.0.1.tgz", + "integrity": "sha1-eg4rztHZcXjsVs48ykjgxW3un40=", + "dev": true, + "requires": { + "boom": "2.7.2", + "hoek": "2.14.0", + "joi": "6.4.1", + "wreck": "6.0.0" + } + }, + "heavy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/heavy/-/heavy-3.0.0.tgz", + "integrity": "sha1-/QEIdiExYy+IVIontVQSws9SKwA=", + "dev": true, + "requires": { + "boom": "2.7.2", + "hoek": "2.14.0", + "joi": "6.4.1" + } + }, + "hoek": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.14.0.tgz", + "integrity": "sha1-gSEWkfUqWoNa5J7b8eickANHaqQ=", + "dev": true + }, + "inert": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/inert/-/inert-2.1.5.tgz", + "integrity": "sha1-eybZTEHGLAPsHU726LRe1WuDSFk=", + "dev": true, + "requires": { + "ammo": "1.0.0", + "boom": "2.7.2", + "hoek": "2.14.0", + "items": "1.1.0", + "joi": "6.4.1", + "lru-cache": "2.6.4" + }, + "dependencies": { + "lru-cache": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.4.tgz", + "integrity": "sha1-JnUZDM0bBwHsL2UqTQ09QA12wN0=", + "dev": true + } + } + }, + "iron": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/iron/-/iron-2.1.2.tgz", + "integrity": "sha1-WR2RiiVAdTxEbY5DfNzwz6gBEU8=", + "dev": true, + "requires": { + "boom": "2.7.2", + "cryptiles": "2.0.4", + "hoek": "2.14.0" + } + }, + "items": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/items/-/items-1.1.0.tgz", + "integrity": "sha1-rZ1VhAsimGDLPRYLMidMLUvZ4mI=", + "dev": true + }, + "joi": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.4.1.tgz", + "integrity": "sha1-9Q9CRTVgBo5jg9oVrC0w3Xzra24=", + "dev": true, + "requires": { + "hoek": "2.14.0", + "isemail": "1.1.1", + "moment": "2.10.3", + "topo": "1.0.2" + }, + "dependencies": { + "isemail": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.1.1.tgz", + "integrity": "sha1-4Mj23D9HCX53dzlcaJYnGqJWw7U=", + "dev": true + }, + "moment": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.10.3.tgz", + "integrity": "sha1-CruZ8wf2UhgwjGk17+KcV7Ggon8=", + "dev": true + } + } + }, + "kilt": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/kilt/-/kilt-1.1.1.tgz", + "integrity": "sha1-d7SmFjyn+lshN6iMFzNCFuwj1ds=", + "dev": true, + "requires": { + "hoek": "2.14.0" + } + }, + "mimos": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mimos/-/mimos-2.0.2.tgz", + "integrity": "sha1-wyQXF+dblZkr54esfdbbGptTmx4=", + "dev": true, + "requires": { + "hoek": "2.14.0", + "mime-db": "1.14.0" + }, + "dependencies": { + "mime-db": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.14.0.tgz", + "integrity": "sha1-1WHxC27mbbUflK5leilRp0IX7YM=", + "dev": true + } + } + }, + "peekaboo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/peekaboo/-/peekaboo-1.0.0.tgz", + "integrity": "sha1-wNspJq1lTSygH3ymUKtFkadk/EI=", + "dev": true + }, + "qs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "dev": true + }, + "shot": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/shot/-/shot-1.5.3.tgz", + "integrity": "sha1-SGEHREO8VHLCNRthpGtOrsAH9Xo=", + "dev": true, + "requires": { + "hoek": "2.14.0" + } + }, + "statehood": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/statehood/-/statehood-2.1.1.tgz", + "integrity": "sha1-AfFwtmxeklqvZ5qdMiulkYb8AAk=", + "dev": true, + "requires": { + "boom": "2.7.2", + "cryptiles": "2.0.4", + "hoek": "2.14.0", + "iron": "2.1.2", + "items": "1.1.0", + "joi": "6.4.1" + } + }, + "subtext": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/subtext/-/subtext-1.1.1.tgz", + "integrity": "sha1-DJGCWuZdUXhVWT2DHjPvdaKEFWs=", + "dev": true, + "requires": { + "boom": "2.7.2", + "content": "1.0.1", + "hoek": "2.14.0", + "pez": "1.0.0", + "qs": "4.0.0", + "wreck": "6.0.0" + }, + "dependencies": { + "content": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content/-/content-1.0.1.tgz", + "integrity": "sha1-gD60s7eJVGD9jGnGhMd1RmmvG6E=", + "dev": true, + "requires": { + "boom": "2.7.2", + "hoek": "2.14.0" + } + }, + "pez": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pez/-/pez-1.0.0.tgz", + "integrity": "sha1-hEMYpc5wku7d/6KV4YB5rHefoBg=", + "dev": true, + "requires": { + "b64": "2.0.0", + "boom": "2.7.2", + "content": "1.0.1", + "hoek": "2.14.0", + "nigel": "1.0.1" + }, + "dependencies": { + "b64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/b64/-/b64-2.0.0.tgz", + "integrity": "sha1-tZlbJPR+v9nxMQF6bntdZHVvtvM=", + "dev": true, + "requires": { + "hoek": "2.14.0" + } + }, + "nigel": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nigel/-/nigel-1.0.1.tgz", + "integrity": "sha1-RjmJr4gSePuqHTzJOCPb0XtDYKE=", + "dev": true, + "requires": { + "hoek": "2.14.0", + "vise": "1.0.0" + }, + "dependencies": { + "vise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vise/-/vise-1.0.0.tgz", + "integrity": "sha1-KDRb5N5aNB4V/SgW/Z6j5zA+jfM=", + "dev": true, + "requires": { + "hoek": "2.14.0" + } + } + } + } + } + } + } + }, + "topo": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.0.2.tgz", + "integrity": "sha1-QhV8N8HeTTeIPM3R1skChHqGDbk=", + "dev": true, + "requires": { + "hoek": "2.14.0" + } + }, + "vision": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vision/-/vision-2.0.1.tgz", + "integrity": "sha1-0BIlW6buQm0GlqNOHfMy/sVeZzw=", + "dev": true, + "requires": { + "boom": "2.7.2", + "hoek": "2.14.0", + "items": "1.1.0", + "joi": "6.4.1" + } + }, + "wreck": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-6.0.0.tgz", + "integrity": "sha1-T0CGaWHl14rOBPMqa38x8/PFFjg=", + "dev": true, + "requires": { + "boom": "2.7.2", + "hoek": "2.14.0" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "requires": { + "inherits": "2.0.3" + } + }, + "hash-stream-validation": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.1.tgz", + "integrity": "sha1-7Mm5l7IYvluzEphii7gHhptz3NE=", + "requires": { + "through2": "2.0.3" + } + }, + "hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "pinkie-promise": "2.0.1" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "highlight.js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=" + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true + }, + "html-to-text": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-3.3.0.tgz", + "integrity": "sha1-aptjxpm4hbt7qEsURr/mh2u/z7c=", + "requires": { + "he": "1.1.1", + "htmlparser2": "3.9.2", + "optimist": "0.6.1", + "underscore": "1.8.3", + "underscore.string": "3.3.4" + }, + "dependencies": { + "domutils": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", + "integrity": "sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=", + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.3.0", + "domutils": "1.6.2", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + } + } + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.3.0", + "domutils": "1.5.1", + "entities": "1.0.0", + "readable-stream": "1.1.14" + }, + "dependencies": { + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "http-parser-js": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", + "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "image-size": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.2.tgz", + "integrity": "sha1-juMW1CmLAouWUJG2c9XxU3re5bQ=" + }, + "imap": { + "version": "0.8.19", + "resolved": "https://registry.npmjs.org/imap/-/imap-0.8.19.tgz", + "integrity": "sha1-NniHOTSrCc6mukh0HyhNoq9Z2NU=", + "requires": { + "readable-stream": "1.1.14", + "utf7": "1.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inherits-ex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/inherits-ex/-/inherits-ex-1.2.0.tgz", + "integrity": "sha1-MVlON25zgZjvdUD9V1lBCl1CQDg=", + "requires": { + "xtend": "4.0.1" + } + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=" + }, + "inline-process-browser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/inline-process-browser/-/inline-process-browser-1.0.0.tgz", + "integrity": "sha1-RqYbFT3TybFiSxoAYm7bT39BTyI=", + "requires": { + "falafel": "1.2.0", + "through2": "0.6.5" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ip-range-check": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ip-range-check/-/ip-range-check-0.0.2.tgz", + "integrity": "sha1-YFyFloeqTxhGORjUYZDYs2maKTw=", + "requires": { + "ipaddr.js": "1.5.4" + } + }, + "ipaddr.js": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.4.tgz", + "integrity": "sha1-liJj2dJhMpVvxcYwtjijDTzf/BQ=" + }, + "is": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", + "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=" + }, + "is-alphabetical": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", + "integrity": "sha1-x3B5zJHU76x3W+EDS/LSQ/lebwg=", + "dev": true + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", + "integrity": "sha1-37SqTRCF4zvbYcLe6cgOnGwZ9Ts=", + "dev": true, + "requires": { + "is-alphabetical": "1.0.1", + "is-decimal": "1.0.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-decimal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", + "integrity": "sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI=", + "dev": true + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-generator": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", + "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-hexadecimal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz", + "integrity": "sha1-bghLvJIGH7sJcexYts5tQE4k2mk=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz", + "integrity": "sha1-PamJFKcKIvCoVj7xURokbG/FVHE=", + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz", + "integrity": "sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-stream-ended": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.3.tgz", + "integrity": "sha1-oEc7Jnx1ZjVIa+7cfjNE5UnRUqw=" + }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", + "dev": true + }, + "is-supported-regexp-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz", + "integrity": "sha1-i1IMhfrnolM4LUsCZS4EVXbhO7g=", + "dev": true + }, + "is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "dev": true, + "requires": { + "text-extensions": "1.7.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-whitespace-character": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", + "integrity": "sha1-muAXbzKCtlRXoZks2whPil+DPjs=", + "dev": true + }, + "is-word-character": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", + "integrity": "sha1-WgP6HqkazopusMfNdw64bWXIvvs=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "7.1.2", + "jasmine-core": "2.8.0" + } + }, + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "dev": true + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "jquery": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", + "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=" + }, + "js-base64": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.0.tgz", + "integrity": "sha512-Wehd+7Pf9tFvGb+ydPm9TjYjV8X1YHOVyG8QyELZxEMqOhemVwGRmoG8iQ/soqI3n8v4xn59zaLxiCJiaaRzKA==" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jschardet": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz", + "integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==" + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", + "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=" + }, + "jsonwebtoken": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-5.4.1.tgz", + "integrity": "sha1-IFXGORlf/lYxT6alHfAkaBhqlpU=", + "requires": { + "jws": "3.1.4", + "ms": "0.7.3" + }, + "dependencies": { + "ms": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz", + "integrity": "sha1-cIFVpeROM/X9D8U+gdDUCpG+H/8=" + } + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jstransform": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-3.0.0.tgz", + "integrity": "sha1-olkats7o2XvzvoMNv6IxO4fNZAs=", + "requires": { + "base62": "0.1.1", + "esprima-fb": "3001.1.0-dev-harmony-fb", + "source-map": "0.1.31" + }, + "dependencies": { + "source-map": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz", + "integrity": "sha1-n3BNDWnZ4TioG63267T94z0VHGE=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "jwa": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", + "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", + "requires": { + "base64url": "2.0.0", + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.9", + "safe-buffer": "5.1.1" + } + }, + "jws": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", + "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", + "requires": { + "base64url": "2.0.0", + "jwa": "1.1.5", + "safe-buffer": "5.1.1" + } + }, + "jwt-simple": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/jwt-simple/-/jwt-simple-0.1.0.tgz", + "integrity": "sha1-VGs0qrAuPNScQ6QnlJizTZQAQeM=" + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "known-css-properties": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.5.0.tgz", + "integrity": "sha1-b/ZpQ+1KW1VlfuCVd5qR9FNvgIQ=", + "dev": true + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "ldap-filter": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.2.2.tgz", + "integrity": "sha1-8rhCvguG2jNSeYUFsx68rlkNd9A=", + "requires": { + "assert-plus": "0.1.5" + }, + "dependencies": { + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" + } + } + }, + "ldapjs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.2.tgz", + "integrity": "sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "backoff": "2.5.0", + "bunyan": "1.8.12", + "dashdash": "1.14.1", + "dtrace-provider": "0.8.6", + "ldap-filter": "0.2.2", + "once": "1.4.0", + "vasync": "1.6.4", + "verror": "1.10.0" + } + }, + "less": { + "version": "https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6", + "integrity": "sha1-dD95WEi4QkZPVjcydtAMY6WS/qM=", + "requires": { + "errno": "0.1.6", + "graceful-fs": "3.0.11", + "image-size": "0.3.5", + "mime": "1.6.0", + "mkdirp": "0.5.1", + "promise": "6.1.0", + "request": "2.83.0", + "source-map": "0.4.4" + }, + "dependencies": { + "asap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", + "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0=", + "optional": true + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "optional": true, + "requires": { + "natives": "1.1.1" + } + }, + "image-size": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.3.5.tgz", + "integrity": "sha1-gyQOqy+1sAsEqrjHSwRx6cunrYw=", + "optional": true + }, + "promise": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz", + "integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=", + "optional": true, + "requires": { + "asap": "1.0.0" + } + } + } + }, + "less-plugin-autoprefix": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/less-plugin-autoprefix/-/less-plugin-autoprefix-1.5.1.tgz", + "integrity": "sha1-vKTlsuSMrGlloXgxQuOzLDwAzgc=", + "requires": { + "autoprefixer": "6.7.7", + "postcss": "5.2.18" + }, + "dependencies": { + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000791", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "libbase64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=" + }, + "libmime": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.1.0.tgz", + "integrity": "sha1-EVAS8WcgUa3IgJqPk5Vf/DZI7fk=", + "requires": { + "iconv-lite": "0.4.15", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" + } + } + }, + "libqp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=" + }, + "lie": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.0.2.tgz", + "integrity": "sha1-/9oh17uibzd8rYZdNkmy/Izjn+o=", + "requires": { + "es3ify": "0.1.4", + "immediate": "3.0.6", + "inline-process-browser": "1.0.0", + "unreachable-branch-transform": "0.3.0" + } + }, + "linkify-it": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz", + "integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=", + "requires": { + "uc.micro": "1.0.3" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "localforage": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.5.5.tgz", + "integrity": "sha1-VfwcOoikf2f1+sbxIxsl/xNVZCM=", + "requires": { + "lie": "3.0.2" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.noop": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-3.0.1.tgz", + "integrity": "sha1-OBiPTWUKOkdCWEObluxFsyYXEzw=" + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.templatesettings": "4.1.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0" + } + }, + "log-driver": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=" + }, + "log-symbols": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.1.0.tgz", + "integrity": "sha512-zLeLrzMA1A2vRF1e/0Mo+LNINzi6jzBylHj5WqvQ/WK/5WCZt8si9SyN4p9llr/HRYvVR1AoXHRHl4WTHyQAzQ==", + "dev": true, + "requires": { + "chalk": "2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "loglevel": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.4.1.tgz", + "integrity": "sha1-lbOD+Ro8J1b9SrCTZn5DCRYfK80=", + "dev": true + }, + "lokijs": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/lokijs/-/lokijs-1.4.1.tgz", + "integrity": "sha1-6he+ktLqfKuhyBbWwgBkJOjbC/4=" + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "longest-streak": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "lru-cache": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", + "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=" + }, + "mailparser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-2.1.0.tgz", + "integrity": "sha512-K5aQPX8O4pXQYv2Lg2SZQnlL+XaI4VoyxcCveUVSt5VDTPokGRouX609zttWiBeDm1dwABw41eliFlaVt8FeUQ==", + "requires": { + "addressparser": "1.0.1", + "he": "1.1.1", + "html-to-text": "3.3.0", + "iconv-lite": "0.4.19", + "libmime": "3.1.0", + "linkify-it": "2.0.3", + "mailsplit": "4.0.2", + "tlds": "1.197.0" + } + }, + "mailsplit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/mailsplit/-/mailsplit-4.0.2.tgz", + "integrity": "sha1-Kdy91XBbKe7LDr9PkFamiGosbf4=", + "requires": { + "libbase64": "0.1.0", + "libmime": "3.1.0", + "libqp": "1.1.0" + } + }, + "make-dir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "requires": { + "pify": "3.0.0" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "markdown-escapes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", + "integrity": "sha1-GZTfLTr0gR3lmmcUk0wrIpJzRRg=", + "dev": true + }, + "markdown-table": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.1.tgz", + "integrity": "sha1-Sz3ToTPRUYuO8NvHCb8qG0gkvIw=", + "dev": true + }, + "marked": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.12.tgz", + "integrity": "sha1-fPJf8iUmMvP+JAa94ljpTu6SdRk=" + }, + "mathml-tag-names": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.0.1.tgz", + "integrity": "sha1-jUEmgWi/htEQK5gQnijlMeejRXg=", + "dev": true + }, + "mdast-util-compact": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", + "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", + "dev": true, + "requires": { + "unist-util-modify-children": "1.1.1", + "unist-util-visit": "1.3.0" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "meteor-promise": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/meteor-promise/-/meteor-promise-0.8.6.tgz", + "integrity": "sha512-HP6tOr67z/9XU2Dr0F2SSr8WRTuE23AG9Dj578DCJPEYHs67OLKBviU8A8rwvbwMD7Lu2+Of+yAMz2Wd8r4yxg==", + "dev": true + }, + "methmeth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/methmeth/-/methmeth-1.1.0.tgz", + "integrity": "sha1-6AomYY5S9cQiKGG7dIUQvRDikIk=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=" + }, + "mime-db": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.32.0.tgz", + "integrity": "sha512-+ZWo/xZN40Tt6S+HyakUxnSOgff+JEdaneLWIm0Z6LmpCn5DMcZntLyUY5c/rTDog28LhXLKOUZKoTxTCAdBVw==" + }, + "mime-type": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/mime-type/-/mime-type-3.0.5.tgz", + "integrity": "sha1-ftKSan2oImifgSVPWYf+lQNiLpo=", + "requires": { + "media-typer": "0.3.0", + "minimatch": "3.0.4", + "path.js": "1.0.7", + "util-ex": "0.3.15" + } + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + }, + "dependencies": { + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + } + } + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "is-plain-obj": "1.1.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha1-fYbPvPNcuCnidUwy4XNV7AUzh5Q=", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "mock-require": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-3.0.1.tgz", + "integrity": "sha1-1e/YNMDaDOxzx7Z3Y9gWfTLYUd4=", + "dev": true, + "requires": { + "get-caller-file": "1.0.2" + } + }, + "modelo": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/modelo/-/modelo-4.2.3.tgz", + "integrity": "sha1-snhYik24f8HlEHrjonfAh2842JQ=" + }, + "modify-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.0.tgz", + "integrity": "sha1-4rbN65zhn5kxelNyLz2/XfXqqrI=", + "dev": true + }, + "module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", + "dev": true + }, + "moment": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", + "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" + }, + "moment-timezone": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.14.tgz", + "integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=", + "requires": { + "moment": "2.20.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "optional": true, + "requires": { + "mkdirp": "0.5.1", + "ncp": "2.0.0", + "rimraf": "2.4.5" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "optional": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "optional": true, + "requires": { + "glob": "6.0.4" + } + } + } + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=" + }, + "natives": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", + "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "optional": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "1.1.4" + } + }, + "node-dogstatsd": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/node-dogstatsd/-/node-dogstatsd-0.0.7.tgz", + "integrity": "sha1-VE0nTJGkE0JqLzxA/3uOiBPP2TA=" + }, + "node-forge": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", + "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=" + }, + "node-pre-gyp": { + "version": "0.6.36", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", + "integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=", + "requires": { + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.3", + "request": "2.83.0", + "rimraf": "2.6.2", + "semver": "5.4.1", + "tar": "2.2.1", + "tar-pack": "3.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + }, + "normalize-selector": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", + "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", + "dev": true + }, + "npm-install-package": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz", + "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", + "dev": true + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "requires": { + "boolbase": "1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object-path": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", + "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha1-DpK2vty1nwIsE9DxlJ3ILRWQnxw=", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", + "integrity": "sha1-gRLYhHExnyerrk1klksSL+ThuJA=", + "dev": true, + "requires": { + "character-entities": "1.2.1", + "character-entities-legacy": "1.1.1", + "character-reference-invalid": "1.1.1", + "is-alphanumerical": "1.0.1", + "is-decimal": "1.0.1", + "is-hexadecimal": "1.0.1" + } + }, + "parse-github-repo-url": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", + "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "path.js": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path.js/-/path.js-1.0.7.tgz", + "integrity": "sha1-fRNrYH3hm/2YugaIdJJih+ZTSTk=", + "requires": { + "escape-string-regexp": "1.0.5", + "inherits-ex": "1.2.0", + "util-ex": "0.3.15" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "phantomjs-prebuilt": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.15.tgz", + "integrity": "sha1-IPhugtM0nFBZF1J3RbekEeCLOQM=", + "dev": true, + "requires": { + "es6-promise": "4.0.5", + "extract-zip": "1.6.6", + "fs-extra": "1.0.0", + "hasha": "2.2.0", + "kew": "0.7.0", + "progress": "1.1.8", + "request": "2.81.0", + "request-progress": "2.0.1", + "which": "1.2.14" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + } + } + }, + "photoswipe": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/photoswipe/-/photoswipe-4.1.2.tgz", + "integrity": "sha1-lcIKdc6iO3DWKZZBytguA8rn95c=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "poplib": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/poplib/-/poplib-0.1.7.tgz", + "integrity": "sha1-L0tYtVkpcjUM2X9IKrpo+OBVdLw=", + "requires": { + "optimist": "0.6.1" + } + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-custom-properties": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.2.0.tgz", + "integrity": "sha512-eNR2h9T9ciKMoQEORrPjH33XeN/nuvVuxArOKmHtsFbGbNss631tgTrKou3/pmjAZbA4QQkhLIkPQkIk3WW+8w==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "postcss": "6.0.16" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-html": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.12.0.tgz", + "integrity": "sha512-KxKUpj7AY7nlCbLcTOYxdfJnGE7QFAfU2n95ADj1Q90RM/pOLdz8k3n4avOyRFs7MDQHcRzJQWM1dehCwJxisQ==", + "dev": true, + "requires": { + "htmlparser2": "3.9.2", + "remark": "8.0.0", + "unist-util-find-all-after": "1.0.1" + }, + "dependencies": { + "domutils": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", + "integrity": "sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.3.0", + "domutils": "1.6.2", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + } + } + }, + "postcss-import": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.0.0.tgz", + "integrity": "sha1-qWLi34LTvFptpqOGhBdHIE9B71s=", + "dev": true, + "requires": { + "postcss": "6.0.16", + "postcss-value-parser": "3.3.0", + "read-cache": "1.0.0", + "resolve": "1.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-less": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-1.1.3.tgz", + "integrity": "sha1-aTBSUnG/441Xk9M6wJwaVGuHu1E=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-media-minmax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-3.0.0.tgz", + "integrity": "sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI=", + "dev": true, + "requires": { + "postcss": "6.0.16" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "postcss-nested": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-3.0.0.tgz", + "integrity": "sha512-1xxmLHSfubuUi6xZZ0zLsNoiKfk3BWQj6fkNMaBJC529wKKLcdeCxXt6KJmDLva+trNyQNwEaE/ZWMA7cve1fA==", + "dev": true, + "requires": { + "postcss": "6.0.16", + "postcss-selector-parser": "3.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-reporter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-5.0.0.tgz", + "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "lodash": "4.17.4", + "log-symbols": "2.1.0", + "postcss": "6.0.16" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + }, + "dependencies": { + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=", + "dev": true + }, + "postcss-safe-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-3.0.1.tgz", + "integrity": "sha1-t1Pv9sfArqXoN1++TN6L+QY/8UI=", + "dev": true, + "requires": { + "postcss": "6.0.16" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-sass": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.2.0.tgz", + "integrity": "sha512-cUmYzkP747fPCQE6d+CH2l1L4VSyIlAzZsok3HPjb5Gzsq3jE+VjpAdGlPsnQ310WKWI42sw+ar0UNN59/f3hg==", + "dev": true, + "requires": { + "gonzales-pe": "4.2.3", + "postcss": "6.0.16" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-scss": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-1.0.3.tgz", + "integrity": "sha1-TACrRA/ByZQTTj1OYAwjNBr2zSc=", + "dev": true, + "requires": { + "postcss": "6.0.16" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-selector-not": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-3.0.1.tgz", + "integrity": "sha1-Lk2y8JZTNsAefOx9tsYN/3ZzNdk=", + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "postcss": "6.0.16" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "4.2.0", + "indexes-of": "1.0.1", + "uniq": "1.0.1" + } + }, + "postcss-sorting": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-3.1.0.tgz", + "integrity": "sha512-YCPTcJwGIInF1LpMD1lIYvMHTGUL4s97o/OraA6eKvoauhhk6vjwOWDDjm6uRKqug/kyDPMKEzmYZ6FtW6RDgw==", + "dev": true, + "requires": { + "lodash": "4.17.4", + "postcss": "6.0.16" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=" + }, + "precond": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "prom-client": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-10.2.2.tgz", + "integrity": "sha512-d3qCBK41qZx00/WVzWOX4tau9FinCztqaECZiGuMI5vGYD//5VSdKMOZPRQKjVh5RkI4Ex98DI0YPsoFnEo1QQ==", + "requires": { + "tdigest": "0.1.1" + } + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "requires": { + "asap": "2.0.6" + } + }, + "prop-assign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prop-assign/-/prop-assign-1.0.0.tgz", + "integrity": "sha1-l2eh+/1wk5CGR6boRtMbT+qnBFk=" + }, + "propprop": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/propprop/-/propprop-0.3.1.tgz", + "integrity": "sha1-oEmjVouJZEAGfRXY7J8zc15XAXg=" + }, + "protobufjs": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.2.tgz", + "integrity": "sha1-WXSNfc8D0tsiwT2p/rAk4Wq4DJE=", + "requires": { + "ascli": "1.0.1", + "bytebuffer": "5.0.1", + "glob": "7.1.2", + "yargs": "3.32.0" + } + }, + "proxyquire": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", + "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=", + "dev": true, + "requires": { + "fill-keys": "1.0.2", + "module-not-found-error": "1.0.1", + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "optional": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pump": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.0.tgz", + "integrity": "sha512-6MYypjOvtiXhBSTOD0Zs5eNjCGfnqi5mPsCsW+dgKTxrZzQMZQNpBo3XRkLx7id753f3EeyHLBqzqqUymIolgw==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.6.tgz", + "integrity": "sha512-BurGAcvezsINL5US9T9wGHHcLNrG6MCp//ECtxron3vcR+Rfx5Anqq7HbZXNJvFQli8FGVsWCAvywEJFV5Hx/Q==", + "requires": { + "duplexify": "3.5.3", + "inherits": "2.0.3", + "pump": "2.0.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "range-parser": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-0.0.4.tgz", + "integrity": "sha1-wEJ//vUcEKy6B4KkbJYC50T/Ygs=" + }, + "rc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.3.tgz", + "integrity": "sha1-UVdakA+N1oOBxxC0cSwhVMPiA1s=", + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + } + }, + "recast": { + "version": "0.10.43", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.10.43.tgz", + "integrity": "sha1-uV1Q9tYHYaX2JS4V2AZ4FoSRzn8=", + "requires": { + "ast-types": "0.8.15", + "esprima-fb": "15001.1001.0-dev-harmony-fb", + "private": "0.1.8", + "source-map": "0.5.7" + }, + "dependencies": { + "esprima-fb": { + "version": "15001.1001.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "redis": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.2.5.tgz", + "integrity": "sha1-+B1XALMmhmCfKcCvsp1TnthTrXg=", + "requires": { + "double-ended-queue": "2.1.0-0" + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remark": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-8.0.0.tgz", + "integrity": "sha512-K0PTsaZvJlXTl9DN6qYlvjTkqSZBFELhROZMrblm2rB+085flN84nz4g/BscKRMqDvhzlK1oQ/xnWQumdeNZYw==", + "dev": true, + "requires": { + "remark-parse": "4.0.0", + "remark-stringify": "4.0.0", + "unified": "6.1.6" + } + }, + "remark-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-4.0.0.tgz", + "integrity": "sha512-XZgICP2gJ1MHU7+vQaRM+VA9HEL3X253uwUM/BGgx3iv6TH2B3bF3B8q00DKcyP9YrJV+/7WOWEWBFF/u8cIsw==", + "dev": true, + "requires": { + "collapse-white-space": "1.0.3", + "is-alphabetical": "1.0.1", + "is-decimal": "1.0.1", + "is-whitespace-character": "1.0.1", + "is-word-character": "1.0.1", + "markdown-escapes": "1.0.1", + "parse-entities": "1.1.1", + "repeat-string": "1.6.1", + "state-toggle": "1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "1.1.0", + "unherit": "1.1.0", + "unist-util-remove-position": "1.1.1", + "vfile-location": "2.0.2", + "xtend": "4.0.1" + } + }, + "remark-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-4.0.0.tgz", + "integrity": "sha512-xLuyKTnuQer3ke9hkU38SUYLiTmS078QOnoFavztmbt/pAJtNSkNtFgR0U//uCcmG0qnyxao+PDuatQav46F1w==", + "dev": true, + "requires": { + "ccount": "1.0.2", + "is-alphanumeric": "1.0.0", + "is-decimal": "1.0.1", + "is-whitespace-character": "1.0.1", + "longest-streak": "2.0.2", + "markdown-escapes": "1.0.1", + "markdown-table": "1.1.1", + "mdast-util-compact": "1.0.1", + "parse-entities": "1.1.1", + "repeat-string": "1.6.1", + "state-toggle": "1.0.0", + "stringify-entities": "1.3.1", + "unherit": "1.1.0", + "xtend": "4.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "requires": { + "throttleit": "1.0.0" + } + }, + "requestretry": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.5.0.tgz", + "integrity": "sha1-7RV7ulNSbt6z7DKo5wSkmYvs5ic=", + "dev": true, + "requires": { + "fg-lodash": "0.0.2", + "request": "2.83.0" + } + }, + "require-from-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.1.tgz", + "integrity": "sha1-xUUjPp19pmFunVmt+zn8n1iGdv8=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "retry": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.8.0.tgz", + "integrity": "sha1-I2dijcDtskex6rZJ3FOshiisLV8=" + }, + "retry-request": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-1.3.2.tgz", + "integrity": "sha1-Wa0k5x+K4/MS1fe0vPRnpeWle9Y=", + "requires": { + "request": "2.76.0", + "through2": "2.0.3" + }, + "dependencies": { + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.16.3" + } + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.10.1" + } + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "requires": { + "chalk": "1.1.3", + "commander": "2.13.0", + "is-my-json-valid": "2.17.1", + "pinkie-promise": "2.0.1" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=" + }, + "request": { + "version": "2.76.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.76.0.tgz", + "integrity": "sha1-vkRQWv73A2CgQ2lVEGvjlF2VVg4=", + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "node-uuid": "1.4.8", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.16.3" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" + } + } + }, + "rgb-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-1.0.0.tgz", + "integrity": "sha1-v6+M2c2RZLWibXHrTxWgllMks8E=" + }, + "rgb2hex": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.0.tgz", + "integrity": "sha1-zNVfhgrgxcTqN1BLlY5ELY0SMls=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "safe-json-stringify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz", + "integrity": "sha1-gaCY9Efku8P/MxKiQ1IbwGDvWRE=", + "optional": true + }, + "saucelabs": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.4.0.tgz", + "integrity": "sha1-uTSpr52ih0s/QKrh/N5QpEZvXzg=", + "dev": true, + "requires": { + "https-proxy-agent": "1.0.0" + } + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "scmp": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/scmp/-/scmp-0.0.3.tgz", + "integrity": "sha1-NkjfLXKUZB5/eGc//CloHZutkHM=" + }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" + }, + "selenium-standalone": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/selenium-standalone/-/selenium-standalone-6.12.0.tgz", + "integrity": "sha1-eJcw2wmhBfHM4SxkJNeV0RxUO9Q=", + "dev": true, + "requires": { + "async": "2.6.0", + "commander": "2.13.0", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "lodash": "4.17.4", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "progress": "2.0.0", + "request": "2.79.0", + "tar-stream": "1.5.2", + "urijs": "1.19.0", + "which": "1.3.0", + "yauzl": "2.9.1" + }, + "dependencies": { + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.13.0", + "is-my-json-valid": "2.17.1", + "pinkie-promise": "2.0.1" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3", + "uuid": "3.1.0" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "tar-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.2.tgz", + "integrity": "sha1-+8bG6DwaGdTLSMfZYXH8JI7/x78=", + "dev": true, + "requires": { + "bl": "1.2.1", + "end-of-stream": "1.4.1", + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.0.1" + } + } + } + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "send": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.1.0.tgz", + "integrity": "sha1-z7COvTzsm3/Bo32f+eh1qXHPRkA=", + "requires": { + "debug": "2.6.9", + "fresh": "0.1.0", + "mime": "1.2.6", + "range-parser": "0.0.4" + }, + "dependencies": { + "mime": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.6.tgz", + "integrity": "sha1-sfhsdowCX6h7SAdfFwnyiuryA2U=" + } + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "sha.js": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", + "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-git": { + "version": "1.85.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.85.0.tgz", + "integrity": "sha1-VjrSke/IoSdzXo+815aWc3dhTNQ=", + "dev": true, + "requires": { + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "slack-client": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/slack-client/-/slack-client-2.0.6.tgz", + "integrity": "sha1-eOuJ9/UnYg4UXM17HY0WvWcLs4M=", + "requires": { + "async": "1.5.2", + "eventemitter3": "1.2.0", + "https-proxy-agent": "1.0.0", + "inherits": "2.0.3", + "lodash": "3.10.1", + "request": "2.83.0", + "retry": "0.8.0", + "url-join": "0.0.1", + "winston": "2.4.0", + "ws": "1.1.5" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "snakeize": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", + "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=" + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.0" + } + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "dev": true, + "requires": { + "atob": "1.1.3", + "resolve-url": "0.2.1", + "source-map-url": "0.3.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "speakeasy": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/speakeasy/-/speakeasy-2.0.0.tgz", + "integrity": "sha1-hckaBxsJpcuGQlkNmDVmFl9XYTo=", + "requires": { + "base32.js": "0.0.1" + } + }, + "specificity": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.2.tgz", + "integrity": "sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A==", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "split-array-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/split-array-stream/-/split-array-stream-1.0.3.tgz", + "integrity": "sha1-0rdajl4Ngk1S/eyLgiWDncLjXfo=", + "requires": { + "async": "2.6.0", + "is-stream-ended": "0.1.3" + } + }, + "split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "dev": true, + "requires": { + "through2": "2.0.3" + } + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "stack-chain": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", + "integrity": "sha1-0ZLJ/06moiyUxN1FkXHj8AzqEoU=", + "dev": true + }, + "stack-generator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-1.1.0.tgz", + "integrity": "sha1-NvapIHUabBD0maE8Msu19RoLiyU=", + "dev": true, + "requires": { + "stackframe": "1.0.4" + }, + "dependencies": { + "stackframe": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", + "integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==", + "dev": true + } + } + }, + "stack-trace": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=" + }, + "stackframe": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", + "integrity": "sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ=", + "dev": true + }, + "stacktrace-gps": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-2.4.4.tgz", + "integrity": "sha1-acgn6dbW9Bz0ONfxleLjy/zyjEQ=", + "dev": true, + "requires": { + "source-map": "0.5.6", + "stackframe": "0.3.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + } + } + }, + "stacktrace-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-1.3.1.tgz", + "integrity": "sha1-Z8qyWJr1xBe5Yvc2mUAne7O2oYs=", + "dev": true, + "requires": { + "error-stack-parser": "1.3.6", + "stack-generator": "1.1.0", + "stacktrace-gps": "2.4.4" + } + }, + "state-toggle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", + "integrity": "sha1-0g+aYWu08MO5i5GSLSW2QKorxCU=", + "dev": true + }, + "stream-events": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.2.tgz", + "integrity": "sha1-q/OfZsCJCk63lbyNXoWbJhW1kLI=", + "requires": { + "stubs": "3.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, + "string-format-obj": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string-format-obj/-/string-format-obj-1.1.1.tgz", + "integrity": "sha1-x2EspOKtkjgSqB2xktwpGFCqH2U=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string.prototype.startswith": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/string.prototype.startswith/-/string.prototype.startswith-0.2.0.tgz", + "integrity": "sha1-2miYLjU6TprEpDtFCiBF0cRFrns=" + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringify-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.1.tgz", + "integrity": "sha1-sVDsLXKsTBtfMktR+2soyc3/BYw=", + "dev": true, + "requires": { + "character-entities-html4": "1.1.1", + "character-entities-legacy": "1.1.1", + "is-alphanumerical": "1.0.1", + "is-hexadecimal": "1.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" + }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", + "dev": true + }, + "stylelint": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-8.4.0.tgz", + "integrity": "sha512-56hPH5mTFnk8LzlEuTWq0epa34fHuS54UFYQidBOFt563RJBNi1nz1F2HK2MoT1X1waq47milvRsRahFCCJs/Q==", + "dev": true, + "requires": { + "autoprefixer": "7.2.5", + "balanced-match": "1.0.0", + "chalk": "2.3.0", + "cosmiconfig": "3.1.0", + "debug": "3.1.0", + "execall": "1.0.0", + "file-entry-cache": "2.0.0", + "get-stdin": "5.0.1", + "globby": "7.1.1", + "globjoin": "0.1.4", + "html-tags": "2.0.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "known-css-properties": "0.5.0", + "lodash": "4.17.4", + "log-symbols": "2.1.0", + "mathml-tag-names": "2.0.1", + "meow": "4.0.0", + "micromatch": "2.3.11", + "normalize-selector": "0.2.0", + "pify": "3.0.0", + "postcss": "6.0.16", + "postcss-html": "0.12.0", + "postcss-less": "1.1.3", + "postcss-media-query-parser": "0.2.3", + "postcss-reporter": "5.0.0", + "postcss-resolve-nested-selector": "0.1.1", + "postcss-safe-parser": "3.0.1", + "postcss-sass": "0.2.0", + "postcss-scss": "1.0.3", + "postcss-selector-parser": "3.1.1", + "postcss-value-parser": "3.3.0", + "resolve-from": "4.0.0", + "specificity": "0.3.2", + "string-width": "2.1.1", + "style-search": "0.1.0", + "sugarss": "1.0.1", + "svg-tags": "1.0.0", + "table": "4.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "map-obj": "2.0.0", + "quick-lru": "1.1.0" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "dev": true + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.7", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.0.tgz", + "integrity": "sha512-Me/kel335m6vMKmEmA6c87Z6DUFW3JqkINRnxkbC+A/PUm0D5Fl2dEBQrPKnqCL9Te/CIa1MUt/0InMJhuC/sw==", + "dev": true, + "requires": { + "camelcase-keys": "4.2.0", + "decamelize-keys": "1.1.0", + "loud-rejection": "1.6.0", + "minimist": "1.2.0", + "minimist-options": "3.0.2", + "normalize-package-data": "2.4.0", + "read-pkg-up": "3.0.0", + "redent": "2.0.0", + "trim-newlines": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + }, + "dependencies": { + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "4.0.0", + "normalize-package-data": "2.4.0", + "path-type": "3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "3.0.0" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "3.2.0", + "strip-indent": "2.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + } + } + }, + "stylelint-order": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-0.8.0.tgz", + "integrity": "sha512-XwJO7rIAt/hnBJjOsDgEwNSeqw+5jE22da4pVKaePbojM9bGwhOoAWV7Q2BL8caOg81IlTesmYCEf8s0+2Cc5g==", + "dev": true, + "requires": { + "lodash": "4.17.4", + "postcss": "6.0.16", + "postcss-sorting": "3.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "sugarss": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-1.0.1.tgz", + "integrity": "sha1-voJtkAPg8kdzX5I2XcP9fxuunkQ=", + "dev": true, + "requires": { + "postcss": "6.0.16" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha1-ES4v4qbSEJvglXaHJDFw6lWJ4UY=", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha1-BYoCHRthn33fOYDXEuo1kM5949U=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "superagent": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", + "integrity": "sha1-5KEbnQR/fT7+s7vlNtnsACHRZAM=", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "cookiejar": "2.1.1", + "debug": "3.1.0", + "extend": "3.0.1", + "form-data": "2.3.1", + "formidable": "1.1.1", + "methods": "1.1.2", + "mime": "1.6.0", + "qs": "6.5.1", + "readable-stream": "2.3.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "formidable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz", + "integrity": "sha1-lriIb3w8NQi5Mta9cMTTqI818ak=", + "dev": true + } + } + }, + "supertest": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.0.0.tgz", + "integrity": "sha1-jUu2j9GDDuBwM7HFpamkAhyWUpY=", + "dev": true, + "requires": { + "methods": "1.1.2", + "superagent": "3.8.2" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "dev": true + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.0", + "lodash": "4.17.4", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", + "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", + "requires": { + "debug": "2.6.9", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tar-stream": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", + "integrity": "sha1-XK2Ed59FyDsfJQjZawnYjHIYr1U=", + "requires": { + "bl": "1.2.1", + "end-of-stream": "1.4.1", + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "tdigest": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", + "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", + "requires": { + "bintrees": "1.0.1" + } + }, + "tempfile": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", + "integrity": "sha1-W8xOrsxKsscH2LwR2ZzMmiyyh/I=", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2", + "uuid": "2.0.3" + }, + "dependencies": { + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + } + } + }, + "text-extensions": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.7.0.tgz", + "integrity": "sha512-AKXZeDq230UaSzaO5s3qQUZOaC7iKbzq0jOFL614R7d9R593HLqAOL0cYoqLdkNrjBSOdmoQI06yigq1TSBXAg==", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "tiny-emitter": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", + "integrity": "sha1-gtJ0aKylrejl/R5tIrV91D69+3w=" + }, + "tlds": { + "version": "1.197.0", + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.197.0.tgz", + "integrity": "sha512-zCyB24s6LWQV+qIhNnL/mODj5vpZhZYIOywuweXTsMet2yFgTtOQtjxxCcwTNtSiUj5wjWJLdi6BTn9EHwvfkA==" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "toastr": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz", + "integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=", + "requires": { + "jquery": "3.2.1" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-off-newlines": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", + "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "trim-trailing-lines": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", + "integrity": "sha1-eu+7eAjfnWafbaLkOMrIxGradoQ=", + "dev": true + }, + "trough": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.1.tgz", + "integrity": "sha1-qf2LA5Swro//guBjOgo2zK1bX4Y=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "twilio": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/twilio/-/twilio-2.9.1.tgz", + "integrity": "sha1-BDv6JAzLM/X3a3cUNMJCGgFEvIU=", + "requires": { + "deprecate": "0.1.0", + "jsonwebtoken": "5.4.1", + "jwt-simple": "0.1.0", + "q": "0.9.7", + "request": "2.55.0", + "scmp": "0.0.3", + "string.prototype.startswith": "0.2.0", + "underscore": "1.8.3" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=" + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=" + }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.16.3" + } + }, + "caseless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.9.0.tgz", + "integrity": "sha1-t7Zc5r8UE4hlOc/VM/CzDv+pz4g=" + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "requires": { + "delayed-stream": "0.0.5" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.10.1" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=" + }, + "form-data": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", + "integrity": "sha1-Jvi8JtpkQOKZy9z7aQNcT3em5GY=", + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime-types": "2.0.14" + } + }, + "har-validator": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", + "integrity": "sha1-2DhCsOtMQ1lgrrEIoGejqpTA7rI=", + "requires": { + "bluebird": "2.11.0", + "chalk": "1.1.3", + "commander": "2.13.0", + "is-my-json-valid": "2.17.1" + } + }, + "hawk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz", + "integrity": "sha1-HnMc45RH+h0PbXB/e87r7A/R7B8=", + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "mime-db": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", + "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=" + }, + "mime-types": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", + "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", + "requires": { + "mime-db": "1.12.0" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "oauth-sign": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.6.0.tgz", + "integrity": "sha1-fb6uRPbKRU4fFoRR1jB0ZzWBPOM=" + }, + "qs": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz", + "integrity": "sha1-9854jld33wtQENp/fE5zujJHD1o=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "request": { + "version": "2.55.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.55.0.tgz", + "integrity": "sha1-11wc32eddrsQD5v/4f5VG1wk6T0=", + "requires": { + "aws-sign2": "0.5.0", + "bl": "0.9.5", + "caseless": "0.9.0", + "combined-stream": "0.0.7", + "forever-agent": "0.6.1", + "form-data": "0.2.0", + "har-validator": "1.8.0", + "hawk": "2.3.1", + "http-signature": "0.10.1", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.0.14", + "node-uuid": "1.4.8", + "oauth-sign": "0.6.0", + "qs": "2.4.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.16.3" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" + } + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz", + "integrity": "sha512-N9IvkQslUGYGC24RkJk1ba99foK6TkwC2FHAEBlQFBP0RxQZS8ZpJuAZcwiY/w9ZJHFQb1aOXBI60OdxhTrwEQ==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "ua-parser-js": { + "version": "0.7.17", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", + "integrity": "sha1-6exflJi57JEOeuOsYmqAXE0J7Kw=" + }, + "uc.micro": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz", + "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=" + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "underscore.string": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz", + "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=", + "requires": { + "sprintf-js": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "unherit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", + "integrity": "sha1-a5qu379z3xdWrZ4xbdmBiFhAzX0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "xtend": "4.0.1" + } + }, + "unified": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", + "integrity": "sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w==", + "dev": true, + "requires": { + "bail": "1.0.2", + "extend": "3.0.1", + "is-plain-obj": "1.1.0", + "trough": "1.0.1", + "vfile": "2.3.0", + "x-is-function": "1.0.4", + "x-is-string": "0.1.0" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "unist-util-find-all-after": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-1.0.1.tgz", + "integrity": "sha1-TlUSq/734GFnga7Pex7XUcAK+Qg=", + "dev": true, + "requires": { + "unist-util-is": "2.1.1" + } + }, + "unist-util-is": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", + "integrity": "sha1-DDEmKeP5YMZukx6BLT2A53AQlHs=", + "dev": true + }, + "unist-util-modify-children": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz", + "integrity": "sha1-ZtfmpEnm9nIguXarPLi166w55R0=", + "dev": true, + "requires": { + "array-iterate": "1.1.1" + } + }, + "unist-util-remove-position": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", + "integrity": "sha1-WoXBVV/BugwQG4ZwfRXlD6TIcbs=", + "dev": true, + "requires": { + "unist-util-visit": "1.3.0" + } + }, + "unist-util-stringify-position": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", + "integrity": "sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw=", + "dev": true + }, + "unist-util-visit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", + "integrity": "sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ==", + "dev": true, + "requires": { + "unist-util-is": "2.1.1" + } + }, + "unreachable-branch-transform": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unreachable-branch-transform/-/unreachable-branch-transform-0.3.0.tgz", + "integrity": "sha1-2ZzExudG0mSSiEW2EdtUsPNHTKo=", + "requires": { + "esmangle-evaluator": "1.0.1", + "recast": "0.10.43", + "through2": "0.6.5" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "urijs": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.0.tgz", + "integrity": "sha512-Qs2odXn0hST5VSPVjpi73CMqtbAoanahaqWBujGU+IyMrMqpWcIhDewxQRhCkmqYxuyvICDcSuLdv2O7ncWBGw==", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-join": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", + "integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g=" + }, + "utf7": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utf7/-/utf7-1.0.2.tgz", + "integrity": "sha1-lV9JCq5lO6IguUVqCod2wZk2CZE=", + "requires": { + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util-ex": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/util-ex/-/util-ex-0.3.15.tgz", + "integrity": "sha1-+SYc2hPEMn0HQMvme+Eife2LAFg=", + "requires": { + "inherits-ex": "1.2.0", + "xtend": "4.0.1" + } + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "validator": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/validator/-/validator-9.1.2.tgz", + "integrity": "sha1-VxG2QT94vZ1WADEwyBtHw56GVGw=", + "dev": true + }, + "vasync": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz", + "integrity": "sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=", + "requires": { + "verror": "1.6.0" + }, + "dependencies": { + "extsprintf": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz", + "integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk=" + }, + "verror": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz", + "integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=", + "requires": { + "extsprintf": "1.2.0" + } + } + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "dev": true, + "requires": { + "is-buffer": "1.1.6", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "1.1.1", + "vfile-message": "1.0.0" + } + }, + "vfile-location": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", + "integrity": "sha1-02dcWch3SY5JK0dW/2Xkrxp1IlU=", + "dev": true + }, + "vfile-message": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", + "integrity": "sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw==", + "dev": true, + "requires": { + "unist-util-stringify-position": "1.1.1" + } + }, + "wdio-dot-reporter": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/wdio-dot-reporter/-/wdio-dot-reporter-0.0.9.tgz", + "integrity": "sha1-kpsq2v1J1rBTT9oGjocxm0fjj+U=", + "dev": true + }, + "wdio-sync": { + "version": "0.6.14", + "resolved": "https://registry.npmjs.org/wdio-sync/-/wdio-sync-0.6.14.tgz", + "integrity": "sha1-odzVkHuh0EFUquYXbGItkQw8qbM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "fibers": "1.0.15", + "object.assign": "4.1.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.10.5" + } + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "webdriverio": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.10.1.tgz", + "integrity": "sha1-Qvekh7czebJ0Oi+uULMUJhX2EXA=", + "dev": true, + "requires": { + "archiver": "2.1.1", + "babel-runtime": "6.26.0", + "css-parse": "2.0.0", + "css-value": "0.0.1", + "deepmerge": "2.0.1", + "ejs": "2.5.7", + "gaze": "1.1.2", + "glob": "7.1.2", + "inquirer": "3.3.0", + "json-stringify-safe": "5.0.1", + "mkdirp": "0.5.1", + "npm-install-package": "2.1.0", + "optimist": "0.6.1", + "q": "1.5.1", + "request": "2.83.0", + "rgb2hex": "0.1.0", + "safe-buffer": "5.1.1", + "supports-color": "5.0.1", + "url": "0.11.0", + "validator": "9.1.2", + "wdio-dot-reporter": "0.0.9", + "wgxpath": "1.0.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "supports-color": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", + "integrity": "sha1-HFMx8iJQyEICgFsvF63xZpnzo5o=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + } + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": "0.4.9", + "websocket-extensions": "0.1.3" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", + "dev": true + }, + "wgxpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", + "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "requires": { + "isexe": "2.0.0" + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "requires": { + "string-width": "1.0.2" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "winston": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.0.tgz", + "integrity": "sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4=", + "requires": { + "async": "1.0.0", + "colors": "1.0.3", + "cycle": "1.0.3", + "eyes": "0.1.8", + "isstream": "0.1.2", + "stack-trace": "0.0.9" + }, + "dependencies": { + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + } + } + }, + "wolfy87-eventemitter": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.4.tgz", + "integrity": "sha512-yUOUSIzZxqBeu6VdnigqYHwwjy5N3CRX5XSHh/YcVpy+Qsx+HkHaEWdmdyAr3NvyBYDraOa5EfNIbu47T5QzIA==" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha1-y9nm514J/F0skAFfIfDECHXg3VE=", + "requires": { + "options": "0.0.6", + "ultron": "1.0.2" + } + }, + "x-is-function": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", + "integrity": "sha1-XSlNw9Joy90GJYDgxd93o5HR+h4=", + "dev": true + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + }, + "xml-crypto": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-0.6.0.tgz", + "integrity": "sha1-RSKeACjLPultxTP6M4DCvzuGrbg=", + "requires": { + "xmldom": "0.1.19", + "xpath.js": "1.1.0" + }, + "dependencies": { + "xmldom": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.19.tgz", + "integrity": "sha1-Yx/Ad3bv2EEYvyUXGzftTQdaCrw=" + } + } + }, + "xml2js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.0.tgz", + "integrity": "sha1-99pSJ33rtkeYMFOtti2XLe5loaw=", + "requires": { + "sax": "1.2.1" + } + }, + "xmlbuilder": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.6.4.tgz", + "integrity": "sha1-gSOsFXbZxmkY9BBJbx/p8Ci4yj4=", + "requires": { + "lodash": "3.10.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + }, + "xolvio-ddp": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/xolvio-ddp/-/xolvio-ddp-0.12.3.tgz", + "integrity": "sha1-NqarlhKyQLWg0cCoNJCK8XwLjwI=", + "dev": true, + "requires": { + "bluebird": "2.11.0", + "ddp-ejson": "0.8.1-3", + "ddp-underscore-patched": "0.8.1-2", + "faye-websocket": "0.9.4", + "request": "2.53.0" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "dev": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "dev": true + }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "caseless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.9.0.tgz", + "integrity": "sha1-t7Zc5r8UE4hlOc/VM/CzDv+pz4g=", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "dev": true + }, + "form-data": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", + "integrity": "sha1-Jvi8JtpkQOKZy9z7aQNcT3em5GY=", + "dev": true, + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime-types": "2.0.14" + } + }, + "hawk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz", + "integrity": "sha1-HnMc45RH+h0PbXB/e87r7A/R7B8=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "dev": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "mime-db": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", + "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=", + "dev": true + }, + "mime-types": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", + "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", + "dev": true, + "requires": { + "mime-db": "1.12.0" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true + }, + "oauth-sign": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.6.0.tgz", + "integrity": "sha1-fb6uRPbKRU4fFoRR1jB0ZzWBPOM=", + "dev": true + }, + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "request": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.53.0.tgz", + "integrity": "sha1-GAo66St7Y5gC5PlUXdj83rcddgw=", + "dev": true, + "requires": { + "aws-sign2": "0.5.0", + "bl": "0.9.5", + "caseless": "0.9.0", + "combined-stream": "0.0.7", + "forever-agent": "0.5.2", + "form-data": "0.2.0", + "hawk": "2.3.1", + "http-signature": "0.10.1", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.0.14", + "node-uuid": "1.4.8", + "oauth-sign": "0.6.0", + "qs": "2.3.3", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + } + } + }, + "xolvio-fiber-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xolvio-fiber-utils/-/xolvio-fiber-utils-2.0.3.tgz", + "integrity": "sha1-vsjXDHQGGjFjFbun0w0lyz6C3FA=", + "dev": true, + "requires": { + "fibers": "1.0.15", + "underscore": "1.8.3" + } + }, + "xolvio-jasmine-expect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xolvio-jasmine-expect/-/xolvio-jasmine-expect-1.1.0.tgz", + "integrity": "sha1-vCud1ghCMR8EV59agtzqaisxnH0=", + "dev": true, + "requires": { + "jasmine-core": "2.8.0" + } + }, + "xolvio-sync-webdriverio": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/xolvio-sync-webdriverio/-/xolvio-sync-webdriverio-9.0.1.tgz", + "integrity": "sha1-WRri2MiqynQiZJWfzM+QtPndUWA=", + "dev": true, + "requires": { + "fibers": "1.0.15", + "meteor-promise": "0.8.6", + "underscore": "1.8.3", + "wdio-sync": "0.6.14", + "webdriverio": "4.10.1", + "xolvio-fiber-utils": "2.0.3" + } + }, + "xpath.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz", + "integrity": "sha1-OBakTtS7NSCRCD0AKjg91RBKX/E=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yaqrcode": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/yaqrcode/-/yaqrcode-0.2.1.tgz", + "integrity": "sha1-7xyzMgNJ9rO7MctoCjeouBS9itc=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "1.0.1" + } + }, + "zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "dev": true, + "requires": { + "archiver-utils": "1.3.0", + "compress-commons": "1.2.2", + "lodash": "4.17.4", + "readable-stream": "2.3.3" + } + } + } +} diff --git a/package.json b/package.json index 0dbf8c3190dcc..dfa5568f4fef2 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ }, "devDependencies": { "autoprefixer": "^7.2.5", + "babel-eslint": "^8.2.1", "babel-mocha-es6-compiler": "^0.1.0", "babel-plugin-array-includes": "^2.0.3", "chimp": "^0.51.0", diff --git a/packages/rocketchat-irc-server/README.md b/packages/rocketchat-irc-server/README.md index eebd8dfeea8f0..9265be4ae4249 100644 --- a/packages/rocketchat-irc-server/README.md +++ b/packages/rocketchat-irc-server/README.md @@ -4,22 +4,14 @@ Provides an IRC Network environmet (using Docker) linking servers ``` docker pull inspircd/inspircd-docker -docker run --name ircd -p 6667:6667 -p 6697:6697 -p 7000:7000 --e "INSP_NET_SUFFIX=.example.com" --e "INSP_NET_NAME=LocalNetwork" --e "INSP_SERVER_NAME=irc.example.com" --e "INSP_ENABLE_DNSBL=no" --e "INSP_LINK1_NAME=irc.example.com" --e "INSP_LINK1_IPADDR=0.0.0.0" --e "INSP_LINK1_PORT=7000" --e "INSP_LINK1_SENDPASS=password" --e "INSP_LINK1_RECVPASS=password" --e "INSP_LINK1_TLS_ON=no" -inspircd/inspircd-docker - docker run --name ircd -p 6667:6667 -p 7000:7000 -e "INSP_NET_SUFFIX=.example.com" -e "INSP_NET_NAME=LocalNetwork" -e "INSP_SERVER_NAME=irc.example.com" -e "INSP_ENABLE_DNSBL=no" -e "INSP_LINK1_NAME=irc.example.com" -e "INSP_LINK1_IPADDR=0.0.0.0" -e "INSP_LINK1_PORT=7000" -e "INSP_LINK1_SENDPASS=password" -e "INSP_LINK1_RECVPASS=password" -e "INSP_LINK1_TLS_ON=no" inspircd/inspircd-docker ``` +For start or stop your network do it +``` +docker start|stop ircd +``` + Add settings for your IRC Network on central admin at Rocket.Chat instance. Connect your IRC client (e.g mIRC, irssi etc) using the port 6667 and connect your Rocket.Chat instance at port 7000. diff --git a/packages/rocketchat-irc-server/server/irc-server-bridge.js b/packages/rocketchat-irc-server/server/irc-server-bridge.js index 5f4a933807d0f..db2acb0e198b0 100644 --- a/packages/rocketchat-irc-server/server/irc-server-bridge.js +++ b/packages/rocketchat-irc-server/server/irc-server-bridge.js @@ -11,19 +11,7 @@ class IrcServer { this.serverName = RocketChat.settings.get('IRC_Server_Name'); this.serverDescription = RocketChat.settings.get('IRC_Server_Description'); - // TODO: Remove it... - console.log('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'); - console.log('>>> IRC host: ', this.ircHost); - console.log('>>> IRC port: ', this.ircPort); - console.log('>>> IRC serverId: ', this.serverId); - console.log('>>> IRC sendPassword: ', this.sendPassword); - console.log('>>> IRC receivePassword: ', this.receivePassword); - console.log('>>> IRC serverName: ', this.serverName); - console.log('>>> IRC serverDescription: ', this.serverDescription); - console.log('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'); - this.logCommands = true; - this.ircServers = {}; this.ircUsers = {}; this.localUsersById = {}; @@ -31,7 +19,6 @@ class IrcServer { this.nextUid = parseInt('a00001', 36); this.socket = new net.Socket; - // TODO It probably should be removed (setNoDelay)... this.socket.setNoDelay(); this.socket.setEncoding('utf-8'); this.socket.setKeepAlive(true); @@ -49,25 +36,40 @@ class IrcServer { connect = () => { console.log(`[irc-server] Attempting connection to IRC on ${ this.ircHost }:${ this.ircPort }`); + this.socket.connect(this.ircPort, this.ircHost, this.onConnect); + return this.state = 'connecting'; } disconnect = () => { this.socket.end(); this.state = 'waitingforconnection'; + return this.cleanup(); } onConnect = () => { + console.log('SID: ', this.serverId); + this.writeCommand({ command: 'PASS', parameters: [this.sendPassword, 'TS', 6, this.serverId] }); + // TODO Check this... TS6 docs + //CAPAB + //source: unregistered server + //propagation: none + //parameters: space separated capability list + + //Sends capabilities of the server. This must include QS and ENCAP. It is also + //strongly recommended to include EX, CHW, IE and KNOCK, and for charybdis TS6 + //also SAVE and EUID. For use with services, SERVICES and RSFNC are strongly + //recommended. this.writeCommand({ command: 'CAPAB', - trailer: 'TBURST EOB ENCAP' + trailer: 'TBURST EOB ENCAP EX CHW IE KNOCK SAVE EUID SERVICES RSFNC' }); this.writeCommand({ @@ -80,6 +82,7 @@ class IrcServer { onClose = () => { console.log('[irc-server] Socket closed, cleaning up state'); + this.state = 'waitingforconnection'; return this.cleanup(); @@ -98,7 +101,6 @@ class IrcServer { } onError = (error) => { - console.log(error); return console.log(`[irc-server] Socket error: ${ error.message }`); } @@ -166,23 +168,6 @@ class IrcServer { let index = 0; - // return (() => { - // const result = []; - - // while ((index * nicksPerMessage) < userIds.length) { - // this.writeCommand({ - // prefix: this.serverId, - // command: 'SJOIN', - // parameters: [timestamp, `#${ room.name }`, '+nt'], - // trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') - // }); - - // result.push(index = index + 1); - // } - - // return result; - // })(); - const result = []; while ((index * nicksPerMessage) < userIds.length) { @@ -219,17 +204,12 @@ class IrcServer { } loginUser = (user) => { - if (this.state !== 'connected') { - return; - } - - if (this.localUsersById[user._id] !== undefined) { + if (this.state !== 'connected' || this.localUsersById[user._id] !== undefined) { return; } this.sendUser(user); - // TODO It should be decomposed return RocketChat.models.Rooms.findWithUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } }).forEach(room => this.joinRoom(user, room)); } @@ -260,16 +240,7 @@ class IrcServer { } logoutUser = (user) => { - if (this.state !== 'connected') { - return; - } - - // TODO Attention here... - // if (Array.from(this.localUsersById).includes(!user._id)) { - // return; - // } - - if (!this.localUsersById.includes(user._id)) { + if (this.state !== 'connected' || !user || !user.id || !this.localUsersById.includes(user._id)) { return; } @@ -285,7 +256,6 @@ class IrcServer { }); } - // TODO Refactoring this self function sendMessage = (message, room) => { if (this.state !== 'connected') { return; @@ -299,6 +269,7 @@ class IrcServer { const lines = message.msg.split('\n'); + // TODO Refactoring this self function return (() => { const result = []; @@ -357,7 +328,6 @@ class IrcServer { RocketChat.models.Rooms.removeUsernameFromAll(user.username); - // TODO Attention about usage of 'delete' here... return delete this.ircUsers[userId]; } @@ -417,7 +387,6 @@ class IrcServer { parseMessage = (command) => { let currentIndex = 0; - // let temp; let split; const result = {}; @@ -429,17 +398,6 @@ class IrcServer { if (command[0] === ':') { split = command.indexOf(' ', currentIndex); - // result.prefix = (() => { - // if (split === -1) { - // currentIndex = command.length; - // return command.substring(1); - // } else { - // temp = command.substring(currentIndex+1, split); - // currentIndex = split + 1; - // return temp; - // } - // })(); - if (split === -1) { currentIndex = command.length; result.prefix = command.substring(1); @@ -452,18 +410,6 @@ class IrcServer { if (currentIndex !== command.length) { split = command.indexOf(' ', currentIndex); - // result.command = (() => { - // if (split === -1) { - // temp = command.substring(currentIndex); - // currentIndex = command.length; - // return temp; - // } else { - // temp = command.substring(currentIndex, split); - // currentIndex = split + 1; - // return temp; - // } - // })(); - if (split === -1) { result.command = command.substring(currentIndex); currentIndex = command.length; @@ -473,26 +419,6 @@ class IrcServer { } } - // result.parameters = (() => { - // const elementResult = []; - - // while (currentIndex !== command.length && command[currentIndex] !== ':') { - // split = command.indexOf(' ', currentIndex); - - // if (split === -1) { - // temp = command.substring(currentIndex); - // currentIndex = command.length; - // elementResult.push(temp); - // } else { - // temp = command.substring(currentIndex, split); - // currentIndex = split + 1; - // elementResult.push(temp); - // } - // } - - // return elementResult; - // })(); - result.parameters = []; while (currentIndex !== command.length && command[currentIndex] !== ':') { @@ -531,7 +457,7 @@ class IrcServer { } return this.socket.write(`${ buffer }\r\n`); - } + }; static handleMalformed(command) { return console.log(`[irc-server] Received invalid command: ${ command }`); @@ -651,11 +577,11 @@ class IrcServer { }); return this.partialMessage = newPartialMessage; - } + }; onReceivePASS = (command) => { if (command.parameters.length !== 4) { - this.handleMalformed(command); + IrcServer.handleMalformed(command); this.disconnect(); return; } @@ -675,17 +601,17 @@ class IrcServer { this.ircServers[this.otherServerId] = {proxiesServers: []}; return this.state = 'bursting'; - } + }; // eslint-disable-next-line no-unused-vars onReceiveCAPAB = (command) => { - // TODO: Review it + // TODO: Review it (search git history) //return this.otherServerCapabilities = command.trailer.split(' '); - } + }; onReceiveSERVER = (command) => { if (command.parameters.length !== 2 || command.trailer == null) { - this.handleMalformed(command); + IrcServer.handleMalformed(command); this.disconnect(); return; } @@ -695,11 +621,11 @@ class IrcServer { this.otherServerName = serverName; return this.ircServers[this.otherServerId].serverName = serverName; - } + }; onReceiveSVINFO = (command) => { if (!command.parameters || command.parameters.length !== 3 || command.trailer == null) { - this.handleMalformed(command); + IrcServer.handleMalformed(command); this.disconnect(); return; } @@ -728,11 +654,11 @@ class IrcServer { console.log('[irc-server] Finished bursting'); return this.state = 'connected'; - } + }; onReceiveSID = (command) => { if (!command.parameters || command.parameters.length !== 3 || command.trailer == null || command.prefix == null) { - this.handleMalformed(command); + IrcServer.handleMalformed(command); return; } @@ -747,11 +673,11 @@ class IrcServer { this.ircServers[connectedTo].proxiesServers.push(serverId); return console.log(`[irc-server] New server connected: ${ serverName } via ${ this.ircServers[connectedTo].serverName }`); - } + }; onReceiveSJOIN = (command) => { if (command.parameters.length !== 3 || command.trailer == null) { - this.handleMalformed(command); + IrcServer.handleMalformed(command); return; } @@ -787,8 +713,8 @@ class IrcServer { onReceiveUID = (command) => { console.log('IRC command.parameters (onReceiveUID): ', command.parameters); - if (command.parameters.length !== 9) { - this.handleMalformed(command); + if (command && command.parameters && command.parameters.length !== 9) { + IrcServer.handleMalformed(command); return; } @@ -797,7 +723,8 @@ class IrcServer { const connectedTo = command.prefix; //TODO Handle nick collisions - //TODO Handle verification that irc and rocketchat users are the same + //TODO Handle verification that irc and rocketchat users are the same (send verification code to IRC user on IRC side) + //TODO Handle modes let user = RocketChat.models.Users.findOne({name: nick}); @@ -847,7 +774,7 @@ class IrcServer { this.ircUsers[ircUserId] = user; return console.log(`[irc-server] Registered user ${ nick } with ircUserId ${ ircUserId }`); - } + }; onReceivePING = (command) => { const source = command.trailer; @@ -858,7 +785,7 @@ class IrcServer { parameters: [this.serverName], trailer: source }); - } + }; onReceivePONG = (command) => { // eslint-disable-next-line no-unused-vars @@ -871,13 +798,13 @@ class IrcServer { const [sourceServerName] = command.parameters; return targetServerId = command.trailer; - } + }; onReceiveEOB = (command) => { const serverId = command.prefix; return console.log(`[irc-server] Finished receiving burst from ${ this.ircServers[serverId].serverName }`); - } + }; onReceiveJOIN = (command) => { const userId = command.prefix; @@ -886,14 +813,14 @@ class IrcServer { const [channelTimestamp, channel] = command.parameters; return RocketChat.models.Rooms.addUsernameByName(channel.substring(1), this.ircUsers[userId].username); - } + }; onReceivePART = (command) => { const userId = command.prefix; const [channel] = command.parameters; return RocketChat.models.Rooms.removeUsernameByName(channel.substring(1), this.ircUsers[userId].username); - } + }; onReceiveQUIT = (command) => { const userId = command.prefix; @@ -902,7 +829,7 @@ class IrcServer { const reason = command.trailer; return this.logoutIrcUser(userId); - } + }; onReceiveINVITE = (command) => { const invitingUserId = command.prefix; @@ -933,7 +860,7 @@ class IrcServer { username: invitedUser.username }); }); - } + }; onReceiveKICK = (command) => { const kickingUserId = command.prefix; @@ -962,7 +889,7 @@ class IrcServer { username: kickedUser.username }); }); - } + }; onReceiveKILL = (command) => { const ircUserId = command.prefix; @@ -984,7 +911,7 @@ class IrcServer { return Meteor.runAsUser(userForKill._id, () => { // TODO Kill user }); - } + }; onReceiveSQUIT = (command) => { let [targetServer] = command.parameters; @@ -998,7 +925,7 @@ class IrcServer { console.log(`[irc-server] IRC server disconnecting: ${ this.ircServers[targetServer].serverName }`); return this.cleanupIrcServer(targetServer); - } + }; onReceivePRIVMSG = (command) => { let room; diff --git a/packages/rocketchat-irc-server/server/irc-server-settings.js b/packages/rocketchat-irc-server/server/irc-server-settings.js index 7cda8743b1505..f52539f2d8d17 100644 --- a/packages/rocketchat-irc-server/server/irc-server-settings.js +++ b/packages/rocketchat-irc-server/server/irc-server-settings.js @@ -18,34 +18,34 @@ Meteor.startup(function() { i18nDescription: 'IRC_Server_Port' }); - this.add('IRC_Server_Id', '777', { + this.add('IRC_Server_Id', '97K', { type: 'string', i18nLabel: 'Id', i18nDescription: 'IRC_Server_Id' }); - this.add('IRC_Server_Send_Password', 'password', { + this.add('IRC_Server_Name', 'irc.example.com', { type: 'string', - i18nLabel: 'Send_Password', - i18nDescription: 'IRC_Server_Send_Password' + i18nLabel: 'Name', + i18nDescription: 'IRC_Server_Name' }); - this.add('IRC_Server_Receive_Password', 'password', { + this.add('IRC_Server_Description', 'Rocket.Chat IRC Server', { type: 'string', - i18nLabel: 'Receive_Password', - i18nDescription: 'IRC_Server_Receive_Password' + i18nLabel: 'Description', + i18nDescription: 'IRC_Server_Description' }); - this.add('IRC_Server_Name', 'irc.example.com', { + this.add('IRC_Server_Send_Password', 'password', { type: 'string', - i18nLabel: 'Name', - i18nDescription: 'IRC_Server_Name' + i18nLabel: 'Send_Password', + i18nDescription: 'IRC_Server_Send_Password' }); - this.add('IRC_Server_Description', 'IRC Network', { + this.add('IRC_Server_Receive_Password', 'password', { type: 'string', - i18nLabel: 'Description', - i18nDescription: 'IRC_Server_Description' + i18nLabel: 'Receive_Password', + i18nDescription: 'IRC_Server_Receive_Password' }); }); }); From 3e4b4532ece9efd99c374ab9e3716ecfe0db143a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lindo=C3=A9lio=20L=C3=A1zaro?= Date: Fri, 9 Feb 2018 08:59:43 -0200 Subject: [PATCH 16/26] Working on RC server connection to a local IRC Network --- packages/rocketchat-irc-server/README.md | 5 +- .../server/irc-server-bridge.js | 954 +----------------- .../server/irc-server.js | 928 +++++++++++++++++ 3 files changed, 932 insertions(+), 955 deletions(-) diff --git a/packages/rocketchat-irc-server/README.md b/packages/rocketchat-irc-server/README.md index 9265be4ae4249..763d2acfe4d99 100644 --- a/packages/rocketchat-irc-server/README.md +++ b/packages/rocketchat-irc-server/README.md @@ -12,7 +12,8 @@ For start or stop your network do it docker start|stop ircd ``` -Add settings for your IRC Network on central admin at Rocket.Chat instance. -Connect your IRC client (e.g mIRC, irssi etc) using the port 6667 and connect your Rocket.Chat instance at port 7000. +- Add settings for your IRC Network on central admin at Rocket.Chat instance. + +- Connect your IRC client (e.g mIRC, irssi etc) using the port 6667 and connect your Rocket.Chat instance at port 7000. Read more in [official InspIRCd image page at Docker Hub](https://hub.docker.com/r/inspircd/inspircd-docker). diff --git a/packages/rocketchat-irc-server/server/irc-server-bridge.js b/packages/rocketchat-irc-server/server/irc-server-bridge.js index db2acb0e198b0..80e7e0306d514 100644 --- a/packages/rocketchat-irc-server/server/irc-server-bridge.js +++ b/packages/rocketchat-irc-server/server/irc-server-bridge.js @@ -1,956 +1,4 @@ -import net from 'net'; -import _ from 'underscore'; - -class IrcServer { - constructor() { - this.ircPort = RocketChat.settings.get('IRC_Server_Port'); - this.ircHost = RocketChat.settings.get('IRC_Server_Host'); - this.serverId = RocketChat.settings.get('IRC_Server_Id'); - this.sendPassword = RocketChat.settings.get('IRC_Server_Send_Password'); - this.receivePassword = RocketChat.settings.get('IRC_Server_Receive_Password'); - this.serverName = RocketChat.settings.get('IRC_Server_Name'); - this.serverDescription = RocketChat.settings.get('IRC_Server_Description'); - - this.logCommands = true; - this.ircServers = {}; - this.ircUsers = {}; - this.localUsersById = {}; - this.localUsersByIrcId = {}; - this.nextUid = parseInt('a00001', 36); - - this.socket = new net.Socket; - this.socket.setNoDelay(); - this.socket.setEncoding('utf-8'); - this.socket.setKeepAlive(true); - this.socket.setTimeout(90000); - - this.socket.on('data', this.onReceiveRawMessage); - this.socket.on('close', this.onClose); - this.socket.on('timeout', this.onTimeout); - this.socket.on('error', this.onError); - - this.partialMessage = ''; - - this.state = 'waitingforconnection'; - } - - connect = () => { - console.log(`[irc-server] Attempting connection to IRC on ${ this.ircHost }:${ this.ircPort }`); - - this.socket.connect(this.ircPort, this.ircHost, this.onConnect); - - return this.state = 'connecting'; - } - - disconnect = () => { - this.socket.end(); - this.state = 'waitingforconnection'; - - return this.cleanup(); - } - - onConnect = () => { - console.log('SID: ', this.serverId); - - this.writeCommand({ - command: 'PASS', - parameters: [this.sendPassword, 'TS', 6, this.serverId] - }); - - // TODO Check this... TS6 docs - //CAPAB - //source: unregistered server - //propagation: none - //parameters: space separated capability list - - //Sends capabilities of the server. This must include QS and ENCAP. It is also - //strongly recommended to include EX, CHW, IE and KNOCK, and for charybdis TS6 - //also SAVE and EUID. For use with services, SERVICES and RSFNC are strongly - //recommended. - this.writeCommand({ - command: 'CAPAB', - trailer: 'TBURST EOB ENCAP EX CHW IE KNOCK SAVE EUID SERVICES RSFNC' - }); - - this.writeCommand({ - command: 'SERVER', parameters: [this.serverName, 1], - trailer: this.serverDescription - }); - - return this.state = 'awaitingpass'; - } - - onClose = () => { - console.log('[irc-server] Socket closed, cleaning up state'); - - this.state = 'waitingforconnection'; - - return this.cleanup(); - } - - onTimeout = () => { - if (this.state === 'connected' || this.state === 'bursting') { - return this.writeCommand({ - command: 'PING', - trailer: this.serverId - }); - } else { - console.log('[irc-server] Timed out waiting for password'); - return this.disconnect(); - } - } - - onError = (error) => { - return console.log(`[irc-server] Socket error: ${ error.message }`); - } - - cleanup = () => { - this.partialMessage = ''; - - if (this.ircServers.length > 0) { - this.cleanupIrcServer(this.otherServerId); - } - - this.localUsersById = {}; - - return this.localUsersByIrcId = {}; - } - - burst = () => { - const users = RocketChat.models.Users.find({statusConnection: 'online'}, { fields: { _id: 1, username: 1, status: 1, name: 1}}).fetch(); - const rooms = RocketChat.models.Rooms.find({}, {fields: { ts: 1, name: 1, usernames: 1, t: 1 } }).fetch(); - - users.forEach(user => this.sendUser(user)); - rooms.forEach(room => this.sendRoom(room)); - - return this.writeCommand({ - command: 'EOB', - prefix: this.serverId - }); - } - - sendUser = (user) => { - const counterString = this.nextUid.toString().toUpperCase(); - - this.nextUid = this.nextUid + 1; - - const data = _.extend(user, {nickTimestamp: this.getTime(), ircUserId: `${ this.serverId }${ counterString }`}); - - this.localUsersById[data._id] = data; - this.localUsersByIrcId[data.ircUserId] = data; - - return this.writeCommand({ - prefix: this.serverId, - command: 'UID', - parameters: [user.username, 1, data.nickTimestamp, '+', user.username, this.serverName, this.ircHost, data.ircUserId, '*'], - trailer: user.name - }); - } - - sendRoom = (room) => { - if (room.t === 'd') { - return; - } - - const userIds = []; - // TODO It probably should to be limited by statusConnection equals 'online' - const subscribedUsers = RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { _id: 1, statusConnection: 1 } }).fetch(); - - subscribedUsers.forEach(user => { - if (user.statusConnection === 'online') { - return userIds.push(this.localUsersById[user._id].ircUserId); - } - }); - - const timestamp = Math.floor(room.ts.getTime() / 1000); - const nickSpace = 510 - 29 - room.name.length; - const nicksPerMessage = Math.floor(nickSpace / 20); - - let index = 0; - - const result = []; - - while ((index * nicksPerMessage) < userIds.length) { - this.writeCommand({ - prefix: this.serverId, - command: 'SJOIN', - parameters: [timestamp, `#${ room.name }`, '+nt'], - trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') - }); - - result.push(index = index + 1); - } - - return result; - } - - joinRoom = (user, room) => { - if (this.state !== 'connected') { - return; - } - - if (room.t === 'd' || this.localUsersById[user._id] === undefined) { - return; - } - - const userId = this.localUsersById[user._id].ircUserId; - const timestamp = Math.floor(room.ts.getTime() / 1000); - - return this.writeCommand({ - prefix: userId, - command: 'JOIN', - parameters: [timestamp, `#${ room.name }`, '+'] - }); - } - - loginUser = (user) => { - if (this.state !== 'connected' || this.localUsersById[user._id] !== undefined) { - return; - } - - this.sendUser(user); - - return RocketChat.models.Rooms.findWithUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } }).forEach(room => this.joinRoom(user, room)); - } - - leaveRoom = (user, room) => { - if (this.state !== 'connected') { - return; - } - - if (room.t === 'd' || !this.localUsersById.includes(user._id)) { - return; - } - - const userId = this.localUsersById[user._id].ircUserId; - - return this.writeCommand({ - prefix: userId, - command: 'PART', - parameters: [`#${ room.name }`] - }); - } - - createRoom = (owner, room) => { - if (room.t === 'd' || this.localUsersById[owner._id] === undefined) { - return; - } - - return this.sendRoom(room); - } - - logoutUser = (user) => { - if (this.state !== 'connected' || !user || !user.id || !this.localUsersById.includes(user._id)) { - return; - } - - const userId = this.localUsersById[user._id].ircUserId; - - delete this.localUsersById[user._id]; - delete this.localUsersByIrcId[userId]; - - return this.writeCommand({ - prefix: userId, - command: 'PART', - trailer: 'Signed out' - }); - } - - sendMessage = (message, room) => { - if (this.state !== 'connected') { - return; - } - - if (this.localUsersById[message.u._id] === undefined) { - return; - } - - const userId = this.localUsersById[message.u._id].ircUserId; - - const lines = message.msg.split('\n'); - - // TODO Refactoring this self function - return (() => { - const result = []; - - lines.forEach(line => { - let messageSpace; - let target; - - line = line.trimRight(); - - if (room.t === 'd') { - messageSpace = 510 - 30; - - //TODO: Change for native ES6 filter maybe? - const targetUsername = _.find(room.usernames, username => username !== message.u.username); - const targetUser = _.find(this.ircUsers, user => user.username === targetUsername); - - target = targetUser.ircUserId; - } else { - //TODO: Should only send message if there are IRC users in the room - messageSpace = 510 - 22 - room.name.length; - target = `#${ room.name }`; - } - - let index = 0; - - result.push((() => { - const elementResult = []; - - while ((index * messageSpace) < line.length) { - this.writeCommand({ - prefix: userId, - command: 'PRIVMSG', - parameters: [target], - trailer: line.substring(index * messageSpace, (index + 1) * messageSpace) - }); - - elementResult.push(index = index + 1); - } - - return elementResult; - })()); - }); - - return result; - })(); - } - - logoutIrcUser = (userId) => { - const user = this.ircUsers[userId]; - - Meteor.users.update({_id: user._id}, { - $set: { - status: 'offline' - } - }); - - RocketChat.models.Rooms.removeUsernameFromAll(user.username); - - return delete this.ircUsers[userId]; - } - - cleanupIrcServer = (serverId) => { - const disconnectedIds = []; - let queue = [serverId]; - - while (queue.length > 0) { - const id = queue.pop(); - disconnectedIds.push(id); - - queue = queue.concat(this.ircServers[id].proxiesServers); - - delete this.ircServers[id]; - } - - return _.filter(this.ircUsers, user => disconnectedIds.includes(user.connectedTo)).forEach(this.logoutIrcUser); - } - - getDirectRoom = (source, target) => { - const rid = [source._id, target._id].sort().join(''); - - RocketChat.models.Rooms.upsert({_id: rid}, { - $set: { - usernames: [source.username, target.username] - }, - $setOnInsert: { - t: 'd', - msgs: 0, - ts: new Date() - } - }); - - RocketChat.models.Subscriptions.upsert({rid, 'u._id': target._id}, { - $setOnInsert: { - name: source.username, - t: 'd', - open: false, - alert: false, - unread: 0, - u: { - _id: target._id, - username: target.username - } - } - }); - - return { - _id: rid, - t: 'd' - }; - } - - static getTime() { - return Math.floor(Date.now() / 1000); - } - - parseMessage = (command) => { - let currentIndex = 0; - let split; - - const result = {}; - - if (command.length === 0) { - return result; - } - - if (command[0] === ':') { - split = command.indexOf(' ', currentIndex); - - if (split === -1) { - currentIndex = command.length; - result.prefix = command.substring(1); - } else { - result.prefix = command.substring(currentIndex+1, split); - currentIndex = split + 1; - } - } - - if (currentIndex !== command.length) { - split = command.indexOf(' ', currentIndex); - - if (split === -1) { - result.command = command.substring(currentIndex); - currentIndex = command.length; - } else { - result.command = command.substring(currentIndex, split); - currentIndex = split + 1; - } - } - - result.parameters = []; - - while (currentIndex !== command.length && command[currentIndex] !== ':') { - split = command.indexOf(' ', currentIndex); - - if (split === -1) { - currentIndex = command.length; - result.parameters.push(command.substring(currentIndex)); - } else { - currentIndex = split + 1; - result.parameters.push(command.substring(currentIndex, split)); - } - } - - if (currentIndex !== command.length) { - result.trailer = command.substring(currentIndex + 1); - } - - return result; - } - - writeCommand = (command) => { - let buffer = command.prefix != null ? `:${ command.prefix } ` : ''; - buffer += command.command; - - if (command.parameters != null && command.parameters.length > 0) { - buffer += ` ${ command.parameters.join(' ') }`; - } - - if (command.trailer != null) { - buffer += ` :${ command.trailer }`; - } - - if (this.logCommands) { - console.log(`[irc-server] Sending Command: ${ buffer }`); - } - - return this.socket.write(`${ buffer }\r\n`); - }; - - static handleMalformed(command) { - return console.log(`[irc-server] Received invalid command: ${ command }`); - } - - onReceiveRawMessage = (data) => { - const dataString = data.toString(); - const lines = dataString.split('\r\n'); - - let newPartialMessage = ''; - if (dataString.substr(dataString.length - 2) !== '\n') { - newPartialMessage = lines.pop(); - } - - let firstLine = true; - - lines.forEach(line => { - line = line.trim(); - - if (firstLine) { - line = this.partialMessage + line; - firstLine = false; - } - - if (this.logCommands) { - console.log(`[irc-server] Received command: ${ line }`); - } - - const command = this.parseMessage(line); - - if (command && command.command != null) { - switch (this.state) { - case 'awaitingpass': - if (command.command === 'PASS') { - this.onReceivePASS(command); - } - break; - case 'bursting': - switch (command.command) { - case 'CAPAB': - this.onReceiveCAPAB(command); - break; - case 'SERVER': - this.onReceiveSERVER(command); - break; - case 'SVINFO': - this.onReceiveSVINFO(command); - break; - case 'UID': - this.onReceiveUID(command); - break; - case 'SID': - this.onReceiveSID(command); - break; - case 'SJOIN': - this.onReceiveSJOIN(command); - break; - case 'PING': - this.onReceivePING(command); - break; - case 'PONG': - this.onReceivePONG(command); - break; - case 'INVITE': - this.onReceiveINVITE(command); - break; - case 'KICK': - this.onReceiveKICK(command); - break; - } - break; - case 'connected': - switch (command.command) { - case 'PING': - this.onReceivePING(command); - break; - case 'PONG': - this.onReceivePONG(command); - break; - case 'EOB': - this.onReceiveEOB(command); - break; - case 'UID': - this.onReceiveUID(command); - break; - case 'SID': - this.onReceiveSID(command); - break; - case 'SJOIN': - this.onReceiveSJOIN(command); - break; - case 'SQUIT': - this.onReceiveSQUIT(command); - break; - case 'JOIN': - this.onReceiveJOIN(command); - break; - case 'PART': - this.onReceivePART(command); - break; - case 'QUIT': - this.onReceiveQUIT(command); - break; - case 'INVITE': - this.onReceiveINVITE(command); - break; - case 'KICK': - this.onReceiveKICK(command); - break; - case 'PRIVMSG': - this.onReceivePRIVMSG(command); - break; - } - break; - } - } - }); - - return this.partialMessage = newPartialMessage; - }; - - onReceivePASS = (command) => { - if (command.parameters.length !== 4) { - IrcServer.handleMalformed(command); - this.disconnect(); - return; - } - - const [password, protocol, protocolVersion, otherServerId] = command.parameters; - - this.otherServerId = otherServerId; - - if (password !== this.receivePassword) { - this.disconnect(); - return; - } - if (protocol !== 'TS' || protocolVersion !== '6') { - this.disconnect(); - return; - } - - this.ircServers[this.otherServerId] = {proxiesServers: []}; - return this.state = 'bursting'; - }; - - // eslint-disable-next-line no-unused-vars - onReceiveCAPAB = (command) => { - // TODO: Review it (search git history) - //return this.otherServerCapabilities = command.trailer.split(' '); - }; - - onReceiveSERVER = (command) => { - if (command.parameters.length !== 2 || command.trailer == null) { - IrcServer.handleMalformed(command); - this.disconnect(); - return; - } - - // eslint-disable-next-line no-unused-vars - const [serverName, hopCount] = command.parameters; - this.otherServerName = serverName; - - return this.ircServers[this.otherServerId].serverName = serverName; - }; - - onReceiveSVINFO = (command) => { - if (!command.parameters || command.parameters.length !== 3 || command.trailer == null) { - IrcServer.handleMalformed(command); - this.disconnect(); - return; - } - - // eslint-disable-next-line no-unused-vars - const [minTS, maxTS, discard] = command.parameters; - - // eslint-disable-next-line no-unused-vars - const timestamp = command.trailer; - - if (minTS > 6 || maxTS < 6) { - this.disconnect(); - return; - } - - console.log('[irc-server] Successfully connected to IRC server, starting to burst'); - - this.writeCommand({ - prefix: this.serverId, - command: 'SVINFO', - parameters: [6, 6, 0], - trailer: this.getTime() - }); - - this.burst(); - console.log('[irc-server] Finished bursting'); - - return this.state = 'connected'; - }; - - onReceiveSID = (command) => { - if (!command.parameters || command.parameters.length !== 3 || command.trailer == null || command.prefix == null) { - IrcServer.handleMalformed(command); - return; - } - - // eslint-disable-next-line no-unused-vars - const [serverName, hopCount, serverId] = command.parameters; - const connectedTo = command.prefix; - - // eslint-disable-next-line no-unused-vars - const serverDescription = command.trailer; - - this.ircServers[serverId] = {serverName, proxiesServers: []}; - this.ircServers[connectedTo].proxiesServers.push(serverId); - - return console.log(`[irc-server] New server connected: ${ serverName } via ${ this.ircServers[connectedTo].serverName }`); - }; - - onReceiveSJOIN = (command) => { - if (command.parameters.length !== 3 || command.trailer == null) { - IrcServer.handleMalformed(command); - return; - } - - // eslint-disable-next-line no-unused-vars - const [channelTimestamp, channel, mode] = command.parameters; - - const userIds = command.trailer.split(' '); - - const users = _.map(userIds, id => { - return { - username: this.ircUsers[id.substring(id.length-9)].username, - isOperator: id[0] === '@' - }; - - }); - - let room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - - if ((room == null)) { - const firstOperator = _.find(users, user => user.isOperator); - if (firstOperator == null) { - return; - } - - RocketChat.createRoom('c', channel.substring(1), firstOperator.username, [], false); - - room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - } - - return RocketChat.models.Rooms.addUsernamesById(room._id, _.map(users, user => user.username)); - } - - onReceiveUID = (command) => { - console.log('IRC command.parameters (onReceiveUID): ', command.parameters); - - if (command && command.parameters && command.parameters.length !== 9) { - IrcServer.handleMalformed(command); - return; - } - - // eslint-disable-next-line no-unused-vars - const [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, ircUserId, gecos] = command.parameters; - const connectedTo = command.prefix; - - //TODO Handle nick collisions - //TODO Handle verification that irc and rocketchat users are the same (send verification code to IRC user on IRC side) - - //TODO Handle modes - let user = RocketChat.models.Users.findOne({name: nick}); - - /** - Nick TS collisions: - If both users are to be collided, we must issue a KILL for the existing - user to all servers. If the new user has a UID then we must also issue a - KILL for that UID back to the server sending us data causing the collision. - - If only the existing user is being collided, we must issue a KILL for the - existing user to all servers except the server sending us data. If the - existing user has a UID and the server sending us data supports TS6 then - we must also issue a KILL for the existing users UID to the server sending - us data. - - If only the new user is being collided, we must issue a KILL for the new user - back to the server sending us data if the new user has a UID. - **/ - - if (!user) { - const userId = Meteor.call('registerUser', { - email: `${ nick }@${ hostname }`, - pass: '', - name: nick - }); - - RocketChat.models.Users.update({_id: userId}, { - $set: { - username: nick, - ircOnly: true - } - }); - - user = RocketChat.models.Users.findOne({_id: userId}); - } - - RocketChat.models.Users.update({_id: user._id}, { - $set: { - status: 'online' - } - }); - - user.nickTimestamp = nickTimestamp; - user.connectedTo = connectedTo; - user.ircUserId = ircUserId; - - this.ircUsers[ircUserId] = user; - - return console.log(`[irc-server] Registered user ${ nick } with ircUserId ${ ircUserId }`); - }; - - onReceivePING = (command) => { - const source = command.trailer; - - return this.writeCommand({ - prefix: this.serverId, - command: 'PONG', - parameters: [this.serverName], - trailer: source - }); - }; - - onReceivePONG = (command) => { - // eslint-disable-next-line no-unused-vars - let targetServerId; - - // eslint-disable-next-line no-unused-vars - const source = command.trailer; - - // eslint-disable-next-line no-unused-vars - const [sourceServerName] = command.parameters; - - return targetServerId = command.trailer; - }; - - onReceiveEOB = (command) => { - const serverId = command.prefix; - - return console.log(`[irc-server] Finished receiving burst from ${ this.ircServers[serverId].serverName }`); - }; - - onReceiveJOIN = (command) => { - const userId = command.prefix; - - // eslint-disable-next-line no-unused-vars - const [channelTimestamp, channel] = command.parameters; - - return RocketChat.models.Rooms.addUsernameByName(channel.substring(1), this.ircUsers[userId].username); - }; - - onReceivePART = (command) => { - const userId = command.prefix; - const [channel] = command.parameters; - - return RocketChat.models.Rooms.removeUsernameByName(channel.substring(1), this.ircUsers[userId].username); - }; - - onReceiveQUIT = (command) => { - const userId = command.prefix; - - // eslint-disable-next-line no-unused-vars - const reason = command.trailer; - - return this.logoutIrcUser(userId); - }; - - onReceiveINVITE = (command) => { - const invitingUserId = command.prefix; - - // eslint-disable-next-line no-unused-vars - const [invitedUserId, channel, channelTimestamp] = command.parameters; - - const invitingUser = this.ircUsers[invitingUserId]; - if (invitingUser == null) { - return; - } - - const invitedUser = this.localUsersByIrcId[invitedUserId]; - if (invitedUser == null) { - return; - } - - const room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - if (room == null) { - return; - } - - console.log(`[irc-server] Inviting ${ invitedUser.username } to ${ room.name }`); - - return Meteor.runAsUser(invitingUser._id, () => { - return Meteor.call('addUserToRoom', { - rid: room._id, - username: invitedUser.username - }); - }); - }; - - onReceiveKICK = (command) => { - const kickingUserId = command.prefix; - const [channel, kickedUserId] = command.parameters; - - const kickingUser = this.ircUsers[kickingUserId]; - if (kickingUser == null) { - return; - } - - const kickedUser = this.localUsersByIrcId[kickedUserId]; - if (kickedUser == null) { - return; - } - - const room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - if (room == null) { - return; - } - - console.log(`[irc-server] Kicking ${ kickedUser.username } from ${ room.name }`); - - return Meteor.runAsUser(kickingUser._id, () => { - return Meteor.call('removeUserFromRoom', { - rid: room._id, - username: kickedUser.username - }); - }); - }; - - onReceiveKILL = (command) => { - const ircUserId = command.prefix; - - console.log('IRC command.parameters: ', command.parameters); - - const userForKill = this.ircUsers[ircUserId]; - if (userForKill == null || userForKill._id == null) { - return; - } - - const killedUser = this.localUsersByIrcId[ircUserId]; - if (killedUser == null) { - return; - } - - console.log(`[irc-server] Killing ${ killedUser.username }`); - - return Meteor.runAsUser(userForKill._id, () => { - // TODO Kill user - }); - }; - - onReceiveSQUIT = (command) => { - let [targetServer] = command.parameters; - - // eslint-disable-next-line no-unused-vars - const comment = command.trailer; - - if (targetServer === this.serverId) { - targetServer = this.otherServerId; - } - - console.log(`[irc-server] IRC server disconnecting: ${ this.ircServers[targetServer].serverName }`); - return this.cleanupIrcServer(targetServer); - }; - - onReceivePRIVMSG = (command) => { - let room; - - const userId = command.prefix; - const [channel] = command.parameters; - const content = command.trailer; - const user = this.ircUsers[userId]; - - if (channel[0] === '#') { - room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - } else { - //TODO Handle direct messages - const targetUser = this.localUsersByIrcId[channel]; - room = this.getDirectRoom(user, targetUser); - } - - const message = { - msg: content, - ts: new Date() - }; - - return RocketChat.sendMessage(user, message, room); - } -} +import { IrcServer } from './irc-server'; if (!!RocketChat.settings.get('IRC_Server_Enabled') === true) { const ircServer = new IrcServer; diff --git a/packages/rocketchat-irc-server/server/irc-server.js b/packages/rocketchat-irc-server/server/irc-server.js index 4eb9724ad57e2..78707c299e4a1 100644 --- a/packages/rocketchat-irc-server/server/irc-server.js +++ b/packages/rocketchat-irc-server/server/irc-server.js @@ -1 +1,929 @@ // TODO Refactoring - transfer IrcServer class (irc-server-bridge) to your specific file + +import net from 'net'; +import _ from 'underscore'; + +export class IrcServer { + constructor() { + this.ircPort = RocketChat.settings.get('IRC_Server_Port'); + this.ircHost = RocketChat.settings.get('IRC_Server_Host'); + this.serverId = RocketChat.settings.get('IRC_Server_Id'); + this.sendPassword = RocketChat.settings.get('IRC_Server_Send_Password'); + this.receivePassword = RocketChat.settings.get('IRC_Server_Receive_Password'); + this.serverName = RocketChat.settings.get('IRC_Server_Name'); + this.serverDescription = RocketChat.settings.get('IRC_Server_Description'); + + this.logCommands = true; + this.ircServers = {}; + this.ircUsers = {}; + this.localUsersById = {}; + this.localUsersByIrcId = {}; + this.nextUid = parseInt('a00001', 36); + + this.socket = new net.Socket; + this.socket.setNoDelay(); + this.socket.setEncoding('utf-8'); + this.socket.setKeepAlive(true); + this.socket.setTimeout(90000); + + this.socket.on('data', this.onReceiveRawMessage); + this.socket.on('close', this.onClose); + this.socket.on('timeout', this.onTimeout); + this.socket.on('error', this.onError); + + this.partialMessage = ''; + + this.state = 'waitingforconnection'; + } + + connect = () => { + console.log(`[irc-server] Attempting connection to IRC on ${ this.ircHost }:${ this.ircPort }`); + + this.socket.connect(this.ircPort, this.ircHost, this.onConnect); + + return this.state = 'connecting'; + } + + disconnect = () => { + this.socket.end(); + this.state = 'waitingforconnection'; + + return this.cleanup(); + } + + onConnect = () => { + this.writeCommand({ + command: 'PASS', + parameters: [this.sendPassword, 'TS', 6, this.serverId] // password, 'TS', TS version, SID + }); + + this.writeCommand({ + command: 'CAPAB', + trailer: 'TBURST EOB QS ENCAP EX CHW IE KNOCK' + }); + + this.writeCommand({ + command: 'SERVER', parameters: [this.serverName, 1], + trailer: this.serverDescription + }); + + return this.state = 'awaitingpass'; + } + + onClose = () => { + console.log('[irc-server] Socket closed, cleaning up state'); + + this.state = 'waitingforconnection'; + + return this.cleanup(); + } + + onTimeout = () => { + if (this.state === 'connected' || this.state === 'bursting') { + return this.writeCommand({ + command: 'PING', + trailer: this.serverId + }); + } else { + console.log('[irc-server] Timed out waiting for password'); + return this.disconnect(); + } + } + + onError = (error) => { + return console.log(`[irc-server] Socket error: ${ error.message }`); + } + + cleanup = () => { + this.partialMessage = ''; + + if (this.ircServers.length > 0) { + this.cleanupIrcServer(this.otherServerId); + } + + this.localUsersById = {}; + + return this.localUsersByIrcId = {}; + } + + burst = () => { + const users = RocketChat.models.Users.find({statusConnection: 'online'}, { fields: { _id: 1, username: 1, status: 1, name: 1}}).fetch(); + const rooms = RocketChat.models.Rooms.find({}, {fields: { ts: 1, name: 1, usernames: 1, t: 1 } }).fetch(); + + users.forEach(user => this.sendUser(user)); + rooms.forEach(room => this.sendRoom(room)); + + return this.writeCommand({ + command: 'EOB', + prefix: this.serverId + }); + } + + sendUser = (user) => { + const counterString = this.nextUid.toString().toUpperCase(); + + this.nextUid = this.nextUid + 1; + + const data = _.extend(user, {nickTimestamp: this.getTime(), ircUserId: `${ this.serverId }${ counterString }`}); + + this.localUsersById[data._id] = data; + this.localUsersByIrcId[data.ircUserId] = data; + + return this.writeCommand({ + prefix: this.serverId, + command: 'UID', + parameters: [user.username, 1, data.nickTimestamp, '+', user.username, this.serverName, this.ircHost, data.ircUserId, '*'], + trailer: user.name + }); + } + + sendRoom = (room) => { + if (room.t === 'd') { + return; + } + + const userIds = []; + // TODO It probably should to be limited by statusConnection equals 'online' + const subscribedUsers = RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { _id: 1, statusConnection: 1 } }).fetch(); + + subscribedUsers.forEach(user => { + if (user.statusConnection === 'online') { + return userIds.push(this.localUsersById[user._id].ircUserId); + } + }); + + const timestamp = Math.floor(room.ts.getTime() / 1000); + const nickSpace = 510 - 29 - room.name.length; + const nicksPerMessage = Math.floor(nickSpace / 20); + + let index = 0; + + const result = []; + + while ((index * nicksPerMessage) < userIds.length) { + this.writeCommand({ + prefix: this.serverId, + command: 'SJOIN', + parameters: [timestamp, `#${ room.name }`, '+nt'], + trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') + }); + + result.push(index = index + 1); + } + + return result; + } + + joinRoom = (user, room) => { + if (this.state !== 'connected') { + return; + } + + if (room.t === 'd' || this.localUsersById[user._id] === undefined) { + return; + } + + const userId = this.localUsersById[user._id].ircUserId; + const timestamp = Math.floor(room.ts.getTime() / 1000); + + return this.writeCommand({ + prefix: userId, + command: 'JOIN', + parameters: [timestamp, `#${ room.name }`, '+'] + }); + } + + loginUser = (user) => { + if (this.state !== 'connected' || this.localUsersById[user._id] !== undefined) { + return; + } + + this.sendUser(user); + + return RocketChat.models.Rooms.findWithUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } }).forEach(room => this.joinRoom(user, room)); + } + + leaveRoom = (user, room) => { + if (this.state !== 'connected') { + return; + } + + if (room.t === 'd' || !this.localUsersById.includes(user._id)) { + return; + } + + const userId = this.localUsersById[user._id].ircUserId; + + return this.writeCommand({ + prefix: userId, + command: 'PART', + parameters: [`#${ room.name }`] + }); + } + + createRoom = (owner, room) => { + if (room.t === 'd' || this.localUsersById[owner._id] === undefined) { + return; + } + + return this.sendRoom(room); + } + + logoutUser = (user) => { + if (this.state !== 'connected' || !user || !user.id || !this.localUsersById.includes(user._id)) { + return; + } + + const userId = this.localUsersById[user._id].ircUserId; + + delete this.localUsersById[user._id]; + delete this.localUsersByIrcId[userId]; + + return this.writeCommand({ + prefix: userId, + command: 'PART', + trailer: 'Signed out' + }); + } + + sendMessage = (message, room) => { + if (this.state !== 'connected' || this.localUsersById[message.u._id] === undefined) { + return; + } + + const userId = this.localUsersById[message.u._id].ircUserId; + + const lines = message.msg.split('\n'); + + const result = []; + + lines.forEach(line => { + let messageSpace; + let target; + + line = line.trimRight(); + + if (room.t === 'd') { + messageSpace = 510 - 30; + + const targetUsername = _.find(room.usernames, username => username !== message.u.username); + const targetUser = _.find(this.ircUsers, user => user.username === targetUsername); + + target = targetUser.ircUserId; + } else { + //TODO: Should only send message if there are IRC users in the room + messageSpace = 510 - 22 - room.name.length; + target = `#${ room.name }`; + } + + let index = 0; + + while ((index * messageSpace) < line.length) { + this.writeCommand({ + prefix: userId, + command: 'PRIVMSG', + parameters: [target], + trailer: line.substring(index * messageSpace, (index + 1) * messageSpace) + }); + + result.push(index = index + 1); + } + }); + + return result; + } + + logoutIrcUser = (userId) => { + const user = this.ircUsers[userId]; + + Meteor.users.update({_id: user._id}, { + $set: { + status: 'offline' + } + }); + + RocketChat.models.Rooms.removeUsernameFromAll(user.username); + + return delete this.ircUsers[userId]; + } + + cleanupIrcServer = (serverId) => { + const disconnectedIds = []; + let queue = [serverId]; + + while (queue.length > 0) { + const id = queue.pop(); + disconnectedIds.push(id); + + queue = queue.concat(this.ircServers[id].proxiesServers); + + delete this.ircServers[id]; + } + + return _.filter(this.ircUsers, user => disconnectedIds.includes(user.connectedTo)).forEach(this.logoutIrcUser); + } + + getDirectRoom = (source, target) => { + const rid = [source._id, target._id].sort().join(''); + + RocketChat.models.Rooms.upsert({_id: rid}, { + $set: { + usernames: [source.username, target.username] + }, + $setOnInsert: { + t: 'd', + msgs: 0, + ts: new Date() + } + }); + + RocketChat.models.Subscriptions.upsert({rid, 'u._id': target._id}, { + $setOnInsert: { + name: source.username, + t: 'd', + open: false, + alert: false, + unread: 0, + u: { + _id: target._id, + username: target.username + } + } + }); + + return { + _id: rid, + t: 'd' + }; + } + + static getTime() { + return Math.floor(Date.now() / 1000); + } + + parseMessage = (command) => { + let currentIndex = 0; + let split; + + const result = {}; + + if (command.length === 0) { + return result; + } + + if (command[0] === ':') { + split = command.indexOf(' ', currentIndex); + + if (split === -1) { + currentIndex = command.length; + result.prefix = command.substring(1); + } else { + result.prefix = command.substring(currentIndex+1, split); + currentIndex = split + 1; + } + } + + if (currentIndex !== command.length) { + split = command.indexOf(' ', currentIndex); + + if (split === -1) { + result.command = command.substring(currentIndex); + currentIndex = command.length; + } else { + result.command = command.substring(currentIndex, split); + currentIndex = split + 1; + } + } + + result.parameters = []; + + while (currentIndex !== command.length && command[currentIndex] !== ':') { + split = command.indexOf(' ', currentIndex); + + if (split === -1) { + currentIndex = command.length; + result.parameters.push(command.substring(currentIndex)); + } else { + currentIndex = split + 1; + result.parameters.push(command.substring(currentIndex, split)); + } + } + + if (currentIndex !== command.length) { + result.trailer = command.substring(currentIndex + 1); + } + + return result; + } + + writeCommand = (command) => { + let buffer = command.prefix != null ? `:${ command.prefix } ` : ''; + buffer += command.command; + + if (command.parameters != null && command.parameters.length > 0) { + buffer += ` ${ command.parameters.join(' ') }`; + } + + if (command.trailer != null) { + buffer += ` :${ command.trailer }`; + } + + if (this.logCommands) { + console.log(`[irc-server] Sending Command: ${ buffer }`); + } + + return this.socket.write(`${ buffer }\r\n`); + }; + + static handleMalformed(command) { + return console.log(`[irc-server] Received invalid command: ${ command }`); + } + + onReceiveRawMessage = (data) => { + const dataString = data.toString(); + const lines = dataString.split('\r\n'); + + let newPartialMessage = ''; + if (dataString.substr(dataString.length - 2) !== '\n') { + newPartialMessage = lines.pop(); + } + + let firstLine = true; + + lines.forEach(line => { + line = line.trim(); + + if (firstLine) { + line = this.partialMessage + line; + firstLine = false; + } + + if (this.logCommands) { + console.log(`[irc-server] Received command: ${ line }`); + } + + const command = this.parseMessage(line); + + if (command && command.command != null) { + switch (this.state) { + case 'awaitingpass': + if (command.command === 'PASS') { + this.onReceivePASS(command); + } + break; + case 'bursting': + switch (command.command) { + case 'CAPAB': + this.onReceiveCAPAB(command); + break; + case 'SERVER': + this.onReceiveSERVER(command); + break; + case 'SVINFO': + this.onReceiveSVINFO(command); + break; + case 'UID': + this.onReceiveUID(command); + break; + case 'SID': + this.onReceiveSID(command); + break; + case 'SJOIN': + this.onReceiveSJOIN(command); + break; + case 'PING': + this.onReceivePING(command); + break; + case 'PONG': + this.onReceivePONG(command); + break; + case 'INVITE': + this.onReceiveINVITE(command); + break; + case 'KICK': + this.onReceiveKICK(command); + break; + } + break; + case 'connected': + switch (command.command) { + case 'PING': + this.onReceivePING(command); + break; + case 'PONG': + this.onReceivePONG(command); + break; + case 'EOB': + this.onReceiveEOB(command); + break; + case 'UID': + this.onReceiveUID(command); + break; + case 'SID': + this.onReceiveSID(command); + break; + case 'SJOIN': + this.onReceiveSJOIN(command); + break; + case 'SQUIT': + this.onReceiveSQUIT(command); + break; + case 'JOIN': + this.onReceiveJOIN(command); + break; + case 'PART': + this.onReceivePART(command); + break; + case 'QUIT': + this.onReceiveQUIT(command); + break; + case 'INVITE': + this.onReceiveINVITE(command); + break; + case 'KICK': + this.onReceiveKICK(command); + break; + case 'PRIVMSG': + this.onReceivePRIVMSG(command); + break; + } + break; + } + } + }); + + return this.partialMessage = newPartialMessage; + }; + + onReceivePASS = (command) => { + if (command.parameters.length !== 4) { + IrcServer.handleMalformed(command); + this.disconnect(); + return; + } + + const [password, protocol, protocolVersion, otherServerId] = command.parameters; + + this.otherServerId = otherServerId; + + if (password !== this.receivePassword) { + this.disconnect(); + return; + } + if (protocol !== 'TS' || protocolVersion !== '6') { + this.disconnect(); + return; + } + + this.ircServers[this.otherServerId] = {proxiesServers: []}; + return this.state = 'bursting'; + }; + + // eslint-disable-next-line no-unused-vars + onReceiveCAPAB = (command) => { + // TODO: Review it (search git history) + //return this.otherServerCapabilities = command.trailer.split(' '); + }; + + onReceiveSERVER = (command) => { + if (command.parameters.length !== 2 || command.trailer == null) { + IrcServer.handleMalformed(command); + this.disconnect(); + return; + } + + // eslint-disable-next-line no-unused-vars + const [serverName, hopCount] = command.parameters; + this.otherServerName = serverName; + + return this.ircServers[this.otherServerId].serverName = serverName; + }; + + onReceiveSVINFO = (command) => { + if (!command.parameters || command.parameters.length !== 3 || command.trailer == null) { + IrcServer.handleMalformed(command); + this.disconnect(); + return; + } + + // eslint-disable-next-line no-unused-vars + const [minTS, maxTS, discard] = command.parameters; + + // eslint-disable-next-line no-unused-vars + const timestamp = command.trailer; + + if (minTS > 6 || maxTS < 6) { + this.disconnect(); + return; + } + + console.log('[irc-server] Successfully connected to IRC server, starting to burst'); + + this.writeCommand({ + prefix: this.serverId, + command: 'SVINFO', + parameters: [6, 6, 0], + trailer: this.getTime() + }); + + this.burst(); + console.log('[irc-server] Finished bursting'); + + return this.state = 'connected'; + }; + + onReceiveSID = (command) => { + if (!command.parameters || command.parameters.length !== 3 || command.trailer == null || command.prefix == null) { + IrcServer.handleMalformed(command); + return; + } + + // eslint-disable-next-line no-unused-vars + const [serverName, hopCount, serverId] = command.parameters; + const connectedTo = command.prefix; + + // eslint-disable-next-line no-unused-vars + const serverDescription = command.trailer; + + this.ircServers[serverId] = {serverName, proxiesServers: []}; + this.ircServers[connectedTo].proxiesServers.push(serverId); + + return console.log(`[irc-server] New server connected: ${ serverName } via ${ this.ircServers[connectedTo].serverName }`); + }; + + onReceiveSJOIN = (command) => { + if (command.parameters.length !== 3 || command.trailer == null) { + IrcServer.handleMalformed(command); + return; + } + + // eslint-disable-next-line no-unused-vars + const [channelTimestamp, channel, mode] = command.parameters; + + const userIds = command.trailer.split(' '); + + const users = _.map(userIds, id => { + return { + username: this.ircUsers[id.substring(id.length-9)].username, + isOperator: id[0] === '@' + }; + + }); + + let room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); + + if ((room == null)) { + const firstOperator = _.find(users, user => user.isOperator); + if (firstOperator == null) { + return; + } + + RocketChat.createRoom('c', channel.substring(1), firstOperator.username, [], false); + + room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); + } + + return RocketChat.models.Rooms.addUsernamesById(room._id, _.map(users, user => user.username)); + } + + onReceiveUID = (command) => { + console.log('IRC command.parameters (onReceiveUID): ', command.parameters); + + if (command && command.parameters && command.parameters.length !== 9) { + IrcServer.handleMalformed(command); + return; + } + + // eslint-disable-next-line no-unused-vars + const [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, ircUserId, gecos] = command.parameters; + const connectedTo = command.prefix; + + //TODO Handle nick collisions + //TODO Handle verification that irc and rocketchat users are the same (send verification code to IRC user on IRC side) + + //TODO Handle modes + let user = RocketChat.models.Users.findOne({name: nick}); + + /** + Nick TS collisions: + If both users are to be collided, we must issue a KILL for the existing + user to all servers. If the new user has a UID then we must also issue a + KILL for that UID back to the server sending us data causing the collision. + + If only the existing user is being collided, we must issue a KILL for the + existing user to all servers except the server sending us data. If the + existing user has a UID and the server sending us data supports TS6 then + we must also issue a KILL for the existing users UID to the server sending + us data. + + If only the new user is being collided, we must issue a KILL for the new user + back to the server sending us data if the new user has a UID. + **/ + + if (!user) { + const userId = Meteor.call('registerUser', { + email: `${ nick }@${ hostname }`, + pass: '', + name: nick + }); + + RocketChat.models.Users.update({_id: userId}, { + $set: { + username: nick, + ircOnly: true + } + }); + + user = RocketChat.models.Users.findOne({_id: userId}); + } + + RocketChat.models.Users.update({_id: user._id}, { + $set: { + status: 'online' + } + }); + + user.nickTimestamp = nickTimestamp; + user.connectedTo = connectedTo; + user.ircUserId = ircUserId; + + this.ircUsers[ircUserId] = user; + + return console.log(`[irc-server] Registered user ${ nick } with ircUserId ${ ircUserId }`); + }; + + onReceivePING = (command) => { + const source = command.trailer; + + return this.writeCommand({ + prefix: this.serverId, + command: 'PONG', + parameters: [this.serverName], + trailer: source + }); + }; + + onReceivePONG = (command) => { + // eslint-disable-next-line no-unused-vars + let targetServerId; + + // eslint-disable-next-line no-unused-vars + const source = command.trailer; + + // eslint-disable-next-line no-unused-vars + const [sourceServerName] = command.parameters; + + return targetServerId = command.trailer; + }; + + onReceiveEOB = (command) => { + const serverId = command.prefix; + + return console.log(`[irc-server] Finished receiving burst from ${ this.ircServers[serverId].serverName }`); + }; + + onReceiveJOIN = (command) => { + const userId = command.prefix; + + // eslint-disable-next-line no-unused-vars + const [channelTimestamp, channel] = command.parameters; + + return RocketChat.models.Rooms.addUsernameByName(channel.substring(1), this.ircUsers[userId].username); + }; + + onReceivePART = (command) => { + const userId = command.prefix; + const [channel] = command.parameters; + + return RocketChat.models.Rooms.removeUsernameByName(channel.substring(1), this.ircUsers[userId].username); + }; + + onReceiveQUIT = (command) => { + const userId = command.prefix; + + // eslint-disable-next-line no-unused-vars + const reason = command.trailer; + + return this.logoutIrcUser(userId); + }; + + onReceiveINVITE = (command) => { + const invitingUserId = command.prefix; + + // eslint-disable-next-line no-unused-vars + const [invitedUserId, channel, channelTimestamp] = command.parameters; + + const invitingUser = this.ircUsers[invitingUserId]; + if (invitingUser == null) { + return; + } + + const invitedUser = this.localUsersByIrcId[invitedUserId]; + if (invitedUser == null) { + return; + } + + const room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); + if (room == null) { + return; + } + + console.log(`[irc-server] Inviting ${ invitedUser.username } to ${ room.name }`); + + return Meteor.runAsUser(invitingUser._id, () => { + return Meteor.call('addUserToRoom', { + rid: room._id, + username: invitedUser.username + }); + }); + }; + + onReceiveKICK = (command) => { + const kickingUserId = command.prefix; + const [channel, kickedUserId] = command.parameters; + + const kickingUser = this.ircUsers[kickingUserId]; + if (kickingUser == null) { + return; + } + + const kickedUser = this.localUsersByIrcId[kickedUserId]; + if (kickedUser == null) { + return; + } + + const room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); + if (room == null) { + return; + } + + console.log(`[irc-server] Kicking ${ kickedUser.username } from ${ room.name }`); + + return Meteor.runAsUser(kickingUser._id, () => { + return Meteor.call('removeUserFromRoom', { + rid: room._id, + username: kickedUser.username + }); + }); + }; + + onReceiveKILL = (command) => { + const ircUserId = command.prefix; + + console.log('IRC command.parameters: ', command.parameters); + + const userForKill = this.ircUsers[ircUserId]; + if (userForKill == null || userForKill._id == null) { + return; + } + + const killedUser = this.localUsersByIrcId[ircUserId]; + if (killedUser == null) { + return; + } + + console.log(`[irc-server] Killing ${ killedUser.username }`); + + return Meteor.runAsUser(userForKill._id, () => { + // TODO Kill user + }); + }; + + onReceiveSQUIT = (command) => { + let [targetServer] = command.parameters; + + // eslint-disable-next-line no-unused-vars + const comment = command.trailer; + + if (targetServer === this.serverId) { + targetServer = this.otherServerId; + } + + console.log(`[irc-server] IRC server disconnecting: ${ this.ircServers[targetServer].serverName }`); + return this.cleanupIrcServer(targetServer); + }; + + onReceivePRIVMSG = (command) => { + let room; + + const userId = command.prefix; + const [channel] = command.parameters; + const content = command.trailer; + const user = this.ircUsers[userId]; + + if (channel[0] === '#') { + room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); + } else { + //TODO Handle direct messages + const targetUser = this.localUsersByIrcId[channel]; + room = this.getDirectRoom(user, targetUser); + } + + const message = { + msg: content, + ts: new Date() + }; + + return RocketChat.sendMessage(user, message, room); + } +} From b99a5d3123357bc374ab0149789cd7014688d956 Mon Sep 17 00:00:00 2001 From: Alan Sikora Date: Mon, 12 Mar 2018 20:55:45 -0300 Subject: [PATCH 17/26] first version, using a RFC2813 implementation --- .meteor/packages | 1 - .meteor/versions | 3 +- package-lock.json | 1337 ++++++++++++++--- package.json | 1 + packages/rocketchat-irc-server/README.md | 19 - packages/rocketchat-irc-server/package.js | 17 - .../server/irc-server-bridge.js | 41 - .../server/irc-server-settings.js | 51 - .../server/irc-server.js | 929 ------------ .../rocketchat-irc/.npm/package/.gitignore | 1 + packages/rocketchat-irc/.npm/package/README | 7 + .../.npm/package/npm-shrinkwrap.json | 20 + packages/rocketchat-irc/package.js | 17 +- .../rocketchat-irc/server/irc-bridge/index.js | 130 ++ .../server/irc-bridge/localHandlers/index.js | 6 + .../irc-bridge/localHandlers/onCreateRoom.js | 15 + .../irc-bridge/localHandlers/onJoinRoom.js | 3 + .../irc-bridge/localHandlers/onLeaveRoom.js | 3 + .../irc-bridge/localHandlers/onLogin.js | 26 + .../irc-bridge/localHandlers/onLogout.js | 5 + .../irc-bridge/localHandlers/onSaveMessage.js | 16 + .../irc-bridge/peerHandlers/disconnected.js | 13 + .../server/irc-bridge/peerHandlers/index.js | 6 + .../irc-bridge/peerHandlers/joinedChannel.js | 22 + .../irc-bridge/peerHandlers/leftChannel.js | 18 + .../irc-bridge/peerHandlers/nickChanged.js | 19 + .../irc-bridge/peerHandlers/sentMessage.js | 68 + .../irc-bridge/peerHandlers/userRegistered.js | 42 + .../rocketchat-irc/server/irc-settings.js | 57 + packages/rocketchat-irc/server/irc.js | 26 + packages/rocketchat-irc/server/server.js | 439 ------ .../server/servers/RFC2813/codes.js | 519 +++++++ .../server/servers/RFC2813/index.js | 162 ++ .../servers/RFC2813/localCommandHandlers.js | 74 + .../server/servers/RFC2813/parseMessage.js | 68 + .../servers/RFC2813/peerCommandHandlers.js | 112 ++ .../rocketchat-irc/server/servers/index.js | 1 + packages/rocketchat-irc/server/settings.js | 78 - .../.app/package-lock.json | 874 +++++++++++ 39 files changed, 3454 insertions(+), 1792 deletions(-) delete mode 100644 packages/rocketchat-irc-server/README.md delete mode 100644 packages/rocketchat-irc-server/package.js delete mode 100644 packages/rocketchat-irc-server/server/irc-server-bridge.js delete mode 100644 packages/rocketchat-irc-server/server/irc-server-settings.js delete mode 100644 packages/rocketchat-irc-server/server/irc-server.js create mode 100644 packages/rocketchat-irc/.npm/package/.gitignore create mode 100644 packages/rocketchat-irc/.npm/package/README create mode 100644 packages/rocketchat-irc/.npm/package/npm-shrinkwrap.json create mode 100644 packages/rocketchat-irc/server/irc-bridge/index.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateRoom.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/localHandlers/onJoinRoom.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/localHandlers/onLeaveRoom.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogout.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/peerHandlers/disconnected.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/peerHandlers/index.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/peerHandlers/leftChannel.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/peerHandlers/nickChanged.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js create mode 100644 packages/rocketchat-irc/server/irc-bridge/peerHandlers/userRegistered.js create mode 100644 packages/rocketchat-irc/server/irc-settings.js create mode 100644 packages/rocketchat-irc/server/irc.js delete mode 100644 packages/rocketchat-irc/server/server.js create mode 100644 packages/rocketchat-irc/server/servers/RFC2813/codes.js create mode 100644 packages/rocketchat-irc/server/servers/RFC2813/index.js create mode 100644 packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js create mode 100644 packages/rocketchat-irc/server/servers/RFC2813/parseMessage.js create mode 100644 packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js create mode 100644 packages/rocketchat-irc/server/servers/index.js delete mode 100644 packages/rocketchat-irc/server/settings.js create mode 100644 packages/rocketchat-livechat/.app/package-lock.json diff --git a/.meteor/packages b/.meteor/packages index cc31cb2d6a5bf..fd1bff1fad1a0 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -149,7 +149,6 @@ rocketchat:version rocketchat:videobridge rocketchat:webrtc rocketchat:wordpress -rocketchat:irc-server konecty:change-case konecty:delayed-task diff --git a/.meteor/versions b/.meteor/versions index 5d94da02f12b5..e8c16fb5f40fc 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -170,8 +170,7 @@ rocketchat:importer-slack@0.0.1 rocketchat:importer-slack-users@1.0.0 rocketchat:integrations@0.0.1 rocketchat:internal-hubot@0.0.1 -rocketchat:irc@0.0.2 -rocketchat:irc-server@0.0.1 +rocketchat:irc@0.0.1 rocketchat:issuelinks@0.0.1 rocketchat:katex@0.0.1 rocketchat:ldap@0.0.1 diff --git a/package-lock.json b/package-lock.json index e4c67bf825bbf..7185b7d6b3640 100644 --- a/package-lock.json +++ b/package-lock.json @@ -264,7 +264,7 @@ "@google-cloud/storage": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-1.4.0.tgz", - "integrity": "sha512-vt1NU7D12OGYPhWfwBD1Q2qFS6Suykorlp3NLaES2W9CW6sEBWLwScxElXt8nPvonYBCFt99jP4g1AqY+0hefw==", + "integrity": "sha1-r1vKwqmGmJxG81Kxyhgzvns4Pds=", "requires": { "@google-cloud/common": "0.13.6", "arrify": "1.0.1", @@ -537,7 +537,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" }, "acorn": { "version": "1.2.2", @@ -645,7 +645,7 @@ "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", "dev": true, "requires": { "micromatch": "2.3.11", @@ -655,7 +655,7 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=" }, "archiver": { "version": "2.1.1", @@ -730,7 +730,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", "dev": true }, "array-find-index": { @@ -1978,7 +1978,7 @@ "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=", "dev": true }, "backoff": { @@ -2036,7 +2036,7 @@ "bcrypt": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz", - "integrity": "sha512-pRyDdo73C8Nim3jwFJ7DWe3TZCgwDfWZ6nHS5LSdU77kWbj1frruvdndP02AOavtD4y8v6Fp2dolbHgp4SDrfg==", + "integrity": "sha1-sC3cbAtS6ha40883XVoy54DatUg=", "requires": { "nan": "2.6.2", "node-pre-gyp": "0.6.36" @@ -2540,6 +2540,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.1.3", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -2573,7 +2574,7 @@ "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", "dev": true }, "cli-cursor": { @@ -2751,7 +2752,7 @@ "configstore": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", - "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", + "integrity": "sha1-CU7mYquD+tmRdnjeEU+q6o/NypA=", "requires": { "dot-prop": "4.2.0", "graceful-fs": "4.1.11", @@ -3083,7 +3084,7 @@ "cosmiconfig": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-3.1.0.tgz", - "integrity": "sha512-zedsBhLSbPBms+kE7AH4vHg6JsKDz6epSv2/+5XHs8ILHlgDciSJfSWf8sX9aQ52Jb7KI7VswUTsLpR/G0cr2Q==", + "integrity": "sha1-ZAqUv5hH8yGABAPNJzr2BmXHM5c=", "dev": true, "requires": { "is-directory": "0.3.1", @@ -3182,7 +3183,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", "requires": { "hoek": "4.2.0" } @@ -3308,6 +3309,14 @@ "meow": "3.7.0" } }, + "dbly-linked-list": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dbly-linked-list/-/dbly-linked-list-0.2.0.tgz", + "integrity": "sha512-Ool7y15f6JRDs0YKx7Dh9uiTb1jS1SZLNdT3Y2q16DlaEghXbMsmODS/XittjR2xztt1gJUpz7jVxpqAPF8VGg==", + "requires": { + "lodash.isequal": "4.5.0" + } + }, "ddp-ejson": { "version": "0.8.1-3", "resolved": "https://registry.npmjs.org/ddp-ejson/-/ddp-ejson-0.8.1-3.tgz", @@ -3326,7 +3335,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "requires": { "ms": "2.0.0" } @@ -3466,7 +3475,7 @@ "dir-glob": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "integrity": "sha1-CyBdK2rvmCOMooZZioIE0p0KADQ=", "dev": true, "requires": { "arrify": "1.0.1", @@ -3476,7 +3485,7 @@ "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", "dev": true, "requires": { "pify": "3.0.0" @@ -3533,7 +3542,7 @@ "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", "requires": { "is-obj": "1.0.1" } @@ -3637,7 +3646,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", - "optional": true, "requires": { "prr": "1.0.1" } @@ -3819,7 +3827,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4230,138 +4238,1042 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "2.0.1" + } + } + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + }, + "dependencies": { + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "flushwritable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flushwritable/-/flushwritable-1.0.0.tgz", + "integrity": "sha1-PjKNj95BKtR+c44751C00pAENJg=" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "formidable": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz", + "integrity": "sha1-Kz9MQRy7X91pXESEPiojUUpDIxo=" + }, + "freeport": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/freeport/-/freeport-1.0.5.tgz", + "integrity": "sha1-JV6KuEFwwzuoXZkOghrl9KGpvF0=", + "dev": true + }, + "fresh": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.1.0.tgz", + "integrity": "sha1-A+SwF4Qk5MLV0ZpU2IFM3JeTSFA=" + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha1-EfgjGPX+e7LNIpZaEI6TBiCCFtg=", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" } - } - } - }, - "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, - "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" - }, - "dependencies": { - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } } }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "string-width": { + "version": "1.0.2", + "bundled": true, "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, "dev": true }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, "dev": true } } }, - "flushwritable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flushwritable/-/flushwritable-1.0.0.tgz", - "integrity": "sha1-PjKNj95BKtR+c44751C00pAENJg=" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "formidable": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz", - "integrity": "sha1-Kz9MQRy7X91pXESEPiojUUpDIxo=" - }, - "freeport": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/freeport/-/freeport-1.0.5.tgz", - "integrity": "sha1-JV6KuEFwwzuoXZkOghrl9KGpvF0=", - "dev": true - }, - "fresh": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.1.0.tgz", - "integrity": "sha1-A+SwF4Qk5MLV0ZpU2IFM3JeTSFA=" - }, - "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "2.4.0", - "klaw": "1.3.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", @@ -4386,7 +5298,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", "dev": true }, "functional-red-black-tree": { @@ -4429,7 +5341,7 @@ "gcp-metadata": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.3.1.tgz", - "integrity": "sha512-5kJPX/RXuqoLmHiOOgkSDk/LI0QaXpEvZ3pvQP4ifjGGDKZKVSOjL/GcDjXA5kLxppFCOjmmsu0Uoop9d1upaQ==", + "integrity": "sha1-MTgURW58PQ7rj4sISzNXnohvgpo=", "requires": { "extend": "3.0.1", "retry-request": "3.3.1" @@ -4449,7 +5361,7 @@ "gcs-resumable-upload": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-0.8.2.tgz", - "integrity": "sha512-PBl1OFABYxubxfYPh000I0+JLbQzBRtNqxzgxYboIQk2tdw7BvjJ2dVukk3YH4QM6GiUwqItyNqWBuxjLH8GhA==", + "integrity": "sha1-N98CRwQwOVp4mmN+csq8gGd66WQ=", "requires": { "buffer-equal": "1.0.0", "configstore": "3.1.1", @@ -4584,7 +5496,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -4616,7 +5528,7 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", "dev": true }, "globby": { @@ -4684,7 +5596,7 @@ "gonzales-pe": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.2.3.tgz", - "integrity": "sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw==", + "integrity": "sha1-QQkXA2JUMyheCu46pHgp/B++tvI=", "dev": true, "requires": { "minimist": "1.1.3" @@ -5617,7 +6529,7 @@ "gtoken": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-1.2.3.tgz", - "integrity": "sha512-wQAJflfoqSgMWrSBk9Fg86q+sd6s7y6uJhIvvIPz++RElGlMtEqsdAR2oWwZ/WTEtp7P9xFbJRrT976oRgzJ/w==", + "integrity": "sha1-VQlXG4r9QyLhJM9mz2gRUoTEdtg=", "requires": { "google-p12-pem": "0.1.2", "jws": "3.1.4", @@ -6071,7 +6983,7 @@ "hawk": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", @@ -6107,7 +7019,7 @@ "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", "dev": true }, "html-tags": { @@ -6240,7 +7152,7 @@ "ignore": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "integrity": "sha1-YSKJv7PCIOGGpYEYYY1b6MG6sCE=", "dev": true }, "image-size": { @@ -6544,7 +7456,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", "dev": true }, "is-builtin-module": { @@ -6849,7 +7761,7 @@ "js-yaml": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", "dev": true, "requires": { "argparse": "1.0.9", @@ -6884,7 +7796,7 @@ "json-parse-better-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "integrity": "sha1-UBg80bLSUnXeBp6ecbRnrJ6rlzo=", "dev": true }, "json-schema": { @@ -7292,6 +8204,11 @@ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "lodash.noop": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-3.0.1.tgz", @@ -7392,7 +8309,7 @@ "longest-streak": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "integrity": "sha1-JCG2upOaRDu5/+v1llhaULTDji4=", "dev": true }, "loose-envify": { @@ -7543,7 +8460,7 @@ "meteor-promise": { "version": "0.8.6", "resolved": "https://registry.npmjs.org/meteor-promise/-/meteor-promise-0.8.6.tgz", - "integrity": "sha512-HP6tOr67z/9XU2Dr0F2SSr8WRTuE23AG9Dj578DCJPEYHs67OLKBviU8A8rwvbwMD7Lu2+Of+yAMz2Wd8r4yxg==", + "integrity": "sha1-aZehWiIfuFnUcgQ/y9yuAZBr8Z0=", "dev": true }, "methmeth": { @@ -7623,7 +8540,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "requires": { "brace-expansion": "1.1.8" } @@ -7636,7 +8553,7 @@ "minimist-options": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "integrity": "sha1-+6TIGRM54T7PTWG+sD8HAQPz2VQ=", "dev": true, "requires": { "arrify": "1.0.1", @@ -7730,7 +8647,7 @@ "moment": { "version": "2.20.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", - "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" + "integrity": "sha1-1usaRsvMFKKy+UNBEsH/iQfzE/0=" }, "moment-timezone": { "version": "0.5.14", @@ -7794,8 +8711,7 @@ "natives": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", - "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", - "optional": true + "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==" }, "natural-compare": { "version": "1.4.0", @@ -7812,7 +8728,7 @@ "no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "integrity": "sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw=", "dev": true, "requires": { "lower-case": "1.1.4" @@ -7856,7 +8772,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { "hosted-git-info": "2.5.0", @@ -7894,7 +8810,7 @@ "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", "requires": { "are-we-there-yet": "1.1.4", "console-control-strings": "1.1.0", @@ -8068,7 +8984,7 @@ "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "integrity": "sha1-5OlPMR6rvIYzoeeZCBZfyiYkG2s=", "dev": true }, "p-try": { @@ -8393,7 +9309,7 @@ "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", "dev": true }, "poplib": { @@ -8508,7 +9424,7 @@ "postcss-html": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.12.0.tgz", - "integrity": "sha512-KxKUpj7AY7nlCbLcTOYxdfJnGE7QFAfU2n95ADj1Q90RM/pOLdz8k3n4avOyRFs7MDQHcRzJQWM1dehCwJxisQ==", + "integrity": "sha1-ObattABd/FRk33mZwPgclbztflA=", "dev": true, "requires": { "htmlparser2": "3.9.2", @@ -8711,7 +9627,7 @@ "postcss-nested": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-3.0.0.tgz", - "integrity": "sha512-1xxmLHSfubuUi6xZZ0zLsNoiKfk3BWQj6fkNMaBJC529wKKLcdeCxXt6KJmDLva+trNyQNwEaE/ZWMA7cve1fA==", + "integrity": "sha1-zeQL0HoHhWXz33Li3CZlhxxySFI=", "dev": true, "requires": { "postcss": "6.0.16", @@ -8786,7 +9702,7 @@ "postcss-reporter": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-5.0.0.tgz", - "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", + "integrity": "sha1-oUF3/RNCgp0pFlPyeG79ZxEDMsM=", "dev": true, "requires": { "chalk": "2.3.0", @@ -8943,7 +9859,7 @@ "postcss-sass": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.2.0.tgz", - "integrity": "sha512-cUmYzkP747fPCQE6d+CH2l1L4VSyIlAzZsok3HPjb5Gzsq3jE+VjpAdGlPsnQ310WKWI42sw+ar0UNN59/f3hg==", + "integrity": "sha1-5VUWRB6VJrpLOApzDToC6eqnjHo=", "dev": true, "requires": { "gonzales-pe": "4.2.3", @@ -9184,7 +10100,7 @@ "postcss-sorting": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-3.1.0.tgz", - "integrity": "sha512-YCPTcJwGIInF1LpMD1lIYvMHTGUL4s97o/OraA6eKvoauhhk6vjwOWDDjm6uRKqug/kyDPMKEzmYZ6FtW6RDgw==", + "integrity": "sha1-r3yQ7nOtElaaV2ZOrwZzXC4lvsA=", "dev": true, "requires": { "lodash": "4.17.4", @@ -9281,7 +10197,7 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=" }, "process-nextick-args": { "version": "1.0.7", @@ -9297,7 +10213,7 @@ "prom-client": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-10.2.2.tgz", - "integrity": "sha512-d3qCBK41qZx00/WVzWOX4tau9FinCztqaECZiGuMI5vGYD//5VSdKMOZPRQKjVh5RkI4Ex98DI0YPsoFnEo1QQ==", + "integrity": "sha1-drOXIHEOwQeW185gE1tdXa+/9hU=", "requires": { "tdigest": "0.1.1" } @@ -9353,8 +10269,7 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "optional": true + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" }, "pseudomap": { "version": "1.0.2", @@ -9393,13 +10308,21 @@ "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, + "queue-fifo": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/queue-fifo/-/queue-fifo-0.2.4.tgz", + "integrity": "sha512-o2xWptfzdw4QLIozUUcRPnppoTNK+X1DxWGd8csnJ1gQUsATfQaDryaGB1MhAu1L48vqPMtH69PZ1kZD82zlVw==", + "requires": { + "dbly-linked-list": "0.2.0" + } + }, "quick-lru": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", @@ -9409,7 +10332,7 @@ "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", "dev": true, "requires": { "is-number": "3.0.0", @@ -9578,7 +10501,7 @@ "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "integrity": "sha1-DDNtOYBVPXVcObWGrjsgqknIK38=", "dev": true }, "regenerator-runtime": { @@ -9589,7 +10512,7 @@ "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "integrity": "sha1-HkmWg3Ix2ot/PPQRTXG1aRoGgN0=", "dev": true, "requires": { "babel-runtime": "6.26.0", @@ -9600,7 +10523,7 @@ "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", "dev": true, "requires": { "is-equal-shallow": "0.1.3" @@ -9643,7 +10566,7 @@ "remark": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-8.0.0.tgz", - "integrity": "sha512-K0PTsaZvJlXTl9DN6qYlvjTkqSZBFELhROZMrblm2rB+085flN84nz4g/BscKRMqDvhzlK1oQ/xnWQumdeNZYw==", + "integrity": "sha1-KHtt8v4RkOJjwdFeSG0/qDVZTW0=", "dev": true, "requires": { "remark-parse": "4.0.0", @@ -9654,7 +10577,7 @@ "remark-parse": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-4.0.0.tgz", - "integrity": "sha512-XZgICP2gJ1MHU7+vQaRM+VA9HEL3X253uwUM/BGgx3iv6TH2B3bF3B8q00DKcyP9YrJV+/7WOWEWBFF/u8cIsw==", + "integrity": "sha1-mfHwSa+sgDgjZuLg0L1VQp3UXYs=", "dev": true, "requires": { "collapse-white-space": "1.0.3", @@ -9677,7 +10600,7 @@ "remark-stringify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-4.0.0.tgz", - "integrity": "sha512-xLuyKTnuQer3ke9hkU38SUYLiTmS078QOnoFavztmbt/pAJtNSkNtFgR0U//uCcmG0qnyxao+PDuatQav46F1w==", + "integrity": "sha1-RDGITAQY8RLaRJkbTjVs/jf6zYc=", "dev": true, "requires": { "ccount": "1.0.2", @@ -9732,7 +10655,7 @@ "request": { "version": "2.83.0", "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", "requires": { "aws-sign2": "0.7.0", "aws4": "1.6.0", @@ -9796,7 +10719,7 @@ "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", "dev": true, "requires": { "path-parse": "1.0.5" @@ -9992,7 +10915,7 @@ "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "requires": { "glob": "7.1.2" } @@ -10033,7 +10956,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" }, "safe-json-stringify": { "version": "1.0.4", @@ -10370,7 +11293,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -10416,7 +11339,7 @@ "slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0" @@ -10438,7 +11361,7 @@ "sntp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", "requires": { "hoek": "4.2.0" } @@ -10466,7 +11389,7 @@ "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", "dev": true, "requires": { "source-map": "0.5.7" @@ -10518,13 +11441,13 @@ "specificity": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.2.tgz", - "integrity": "sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A==", + "integrity": "sha1-meZRHs7vD42bV5JJN6rCyxPRPEI=", "dev": true }, "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "integrity": "sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k=", "dev": true, "requires": { "through": "2.3.8" @@ -10542,7 +11465,7 @@ "split2": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", - "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "integrity": "sha1-GGsldbz4PoW30YRldWI47k7kJJM=", "dev": true, "requires": { "through2": "2.0.3" @@ -10586,7 +11509,7 @@ "stackframe": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", - "integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==", + "integrity": "sha1-NXskqZL5Qny6a1RdlqFO0svKGHs=", "dev": true } } @@ -10678,7 +11601,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "requires": { "safe-buffer": "5.1.1" } @@ -10745,7 +11668,7 @@ "stylelint": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-8.4.0.tgz", - "integrity": "sha512-56hPH5mTFnk8LzlEuTWq0epa34fHuS54UFYQidBOFt563RJBNi1nz1F2HK2MoT1X1waq47milvRsRahFCCJs/Q==", + "integrity": "sha1-wtuusXI2kXgZ+SBuHA31/d9vg8M=", "dev": true, "requires": { "autoprefixer": "7.2.5", @@ -10835,7 +11758,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -10909,7 +11832,7 @@ "meow": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.0.tgz", - "integrity": "sha512-Me/kel335m6vMKmEmA6c87Z6DUFW3JqkINRnxkbC+A/PUm0D5Fl2dEBQrPKnqCL9Te/CIa1MUt/0InMJhuC/sw==", + "integrity": "sha1-/VhV3QCNtbksVSCC2xwwfLogsp0=", "dev": true, "requires": { "camelcase-keys": "4.2.0", @@ -10942,7 +11865,7 @@ "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", "dev": true, "requires": { "pify": "3.0.0" @@ -11004,7 +11927,7 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", "dev": true }, "source-map": { @@ -11016,7 +11939,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", @@ -11270,7 +12193,7 @@ "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", "dev": true, "requires": { "ajv": "5.5.2", @@ -11322,7 +12245,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", @@ -11362,7 +12285,7 @@ "tar-pack": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", - "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", + "integrity": "sha1-4dvAOpudO6B+iWrQJzF+tnmhCh8=", "requires": { "debug": "2.6.9", "fstream": "1.0.11", @@ -11414,7 +12337,7 @@ "text-extensions": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.7.0.tgz", - "integrity": "sha512-AKXZeDq230UaSzaO5s3qQUZOaC7iKbzq0jOFL614R7d9R593HLqAOL0cYoqLdkNrjBSOdmoQI06yigq1TSBXAg==", + "integrity": "sha1-+qq6JiXtdG1WiiPk0KrNm/CKizk=", "dev": true }, "text-table": { @@ -11456,7 +12379,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", "dev": true, "requires": { "os-tmpdir": "1.0.2" @@ -11888,7 +12811,7 @@ "unified": { "version": "6.1.6", "resolved": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", - "integrity": "sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w==", + "integrity": "sha1-Xqf4B6CJjx+Kze7+XyX6oBDMQrE=", "dev": true, "requires": { "bail": "1.0.2", @@ -11956,7 +12879,7 @@ "unist-util-visit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", - "integrity": "sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ==", + "integrity": "sha1-Qcp8gpgf0c5sdiqsOX/CTjVxFEQ=", "dev": true, "requires": { "unist-util-is": "2.1.1" @@ -12129,7 +13052,7 @@ "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "integrity": "sha1-5i2OcrIOg8MkvGxnJ47ickiL+Eo=", "dev": true, "requires": { "is-buffer": "1.1.6", @@ -12147,7 +13070,7 @@ "vfile-message": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", - "integrity": "sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw==", + "integrity": "sha1-pq2wR06kAPol2Snx1nOr6moX41k=", "dev": true, "requires": { "unist-util-stringify-position": "1.1.1" @@ -12290,7 +13213,7 @@ "wide-align": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=", "requires": { "string-width": "1.0.2" } @@ -12323,7 +13246,7 @@ "wolfy87-eventemitter": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.4.tgz", - "integrity": "sha512-yUOUSIzZxqBeu6VdnigqYHwwjy5N3CRX5XSHh/YcVpy+Qsx+HkHaEWdmdyAr3NvyBYDraOa5EfNIbu47T5QzIA==" + "integrity": "sha1-UCHSlS02EcvNGVFJcR2bWVzRHUg=" }, "wordwrap": { "version": "0.0.3", @@ -12356,7 +13279,7 @@ "write-file-atomic": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "integrity": "sha1-H/YVdcLipOjlENb6TiQ8zhg5mas=", "requires": { "graceful-fs": "4.1.11", "imurmurhash": "0.1.4", diff --git a/package.json b/package.json index dfa5568f4fef2..dea53a197a97c 100644 --- a/package.json +++ b/package.json @@ -159,6 +159,7 @@ "poplib": "^0.1.7", "prom-client": "^10.2.2", "querystring": "0.2.0", + "queue-fifo": "^0.2.4", "redis": "2.2.5", "semver": "^5.4.1", "slack-client": "2.0.6", diff --git a/packages/rocketchat-irc-server/README.md b/packages/rocketchat-irc-server/README.md deleted file mode 100644 index 763d2acfe4d99..0000000000000 --- a/packages/rocketchat-irc-server/README.md +++ /dev/null @@ -1,19 +0,0 @@ -**IRC Server Federation** - -Provides an IRC Network environmet (using Docker) linking servers - -``` -docker pull inspircd/inspircd-docker -docker run --name ircd -p 6667:6667 -p 7000:7000 -e "INSP_NET_SUFFIX=.example.com" -e "INSP_NET_NAME=LocalNetwork" -e "INSP_SERVER_NAME=irc.example.com" -e "INSP_ENABLE_DNSBL=no" -e "INSP_LINK1_NAME=irc.example.com" -e "INSP_LINK1_IPADDR=0.0.0.0" -e "INSP_LINK1_PORT=7000" -e "INSP_LINK1_SENDPASS=password" -e "INSP_LINK1_RECVPASS=password" -e "INSP_LINK1_TLS_ON=no" inspircd/inspircd-docker -``` - -For start or stop your network do it -``` -docker start|stop ircd -``` - -- Add settings for your IRC Network on central admin at Rocket.Chat instance. - -- Connect your IRC client (e.g mIRC, irssi etc) using the port 6667 and connect your Rocket.Chat instance at port 7000. - -Read more in [official InspIRCd image page at Docker Hub](https://hub.docker.com/r/inspircd/inspircd-docker). diff --git a/packages/rocketchat-irc-server/package.js b/packages/rocketchat-irc-server/package.js deleted file mode 100644 index 5b28aee5595f7..0000000000000 --- a/packages/rocketchat-irc-server/package.js +++ /dev/null @@ -1,17 +0,0 @@ -Package.describe({ - name: 'rocketchat:irc-server', - version: '0.0.1', - summary: 'RocketChat support for federating with IRC servers as a leaf node', - git: '' -}); - -Package.onUse(function(api) { - api.use([ - 'ecmascript', - 'underscore', - 'rocketchat:lib' - ]); - - api.addFiles('server/irc-server-bridge.js', 'server'); - api.addFiles('server/irc-server-settings.js', 'server'); -}); diff --git a/packages/rocketchat-irc-server/server/irc-server-bridge.js b/packages/rocketchat-irc-server/server/irc-server-bridge.js deleted file mode 100644 index 80e7e0306d514..0000000000000 --- a/packages/rocketchat-irc-server/server/irc-server-bridge.js +++ /dev/null @@ -1,41 +0,0 @@ -import { IrcServer } from './irc-server'; - -if (!!RocketChat.settings.get('IRC_Server_Enabled') === true) { - const ircServer = new IrcServer; - - const IrcServerLoginer = function(login) { - if (login.user != null) { ircServer.loginUser(login.user); } - return login; - }; - - const IrcServerSender = (message, room) => ircServer.sendMessage(message, room); - - const IrcServerRoomJoiner = function(user, room) { - ircServer.joinRoom(user, room); - return room; - }; - - const IrcServerRoomLeaver = function(user, room) { - ircServer.leaveRoom(user, room); - return room; - }; - - const IrcServerLogoutCleanUper = function(user) { - ircServer.logoutUser(user); - return user; - }; - - const IrcServerRoomCreator = (owner, room) => ircServer.createRoom(owner, room); - - RocketChat.callbacks.add('afterValidateLogin', IrcServerLoginer, RocketChat.callbacks.priority.LOW, 'irc-server-loginer'); - RocketChat.callbacks.add('afterSaveMessage', IrcServerSender, RocketChat.callbacks.priority.LOW, 'irc-server-sender'); - RocketChat.callbacks.add('beforeJoinRoom', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner'); - RocketChat.callbacks.add('beforeCreateChannel', IrcServerRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-server-room-joiner-create-channel'); - RocketChat.callbacks.add('beforeLeaveRoom', IrcServerRoomLeaver, RocketChat.callbacks.priority.LOW, 'irc-server-room-leaver'); - RocketChat.callbacks.add('afterLogoutCleanUp', IrcServerLogoutCleanUper, RocketChat.callbacks.priority.LOW, 'irc-server-clean-up'); - RocketChat.callbacks.add('afterCreateRoom', IrcServerRoomCreator, RocketChat.callbacks.priority.LOW, 'irc-server-room-creator'); - - Meteor.startup(() => { - Meteor.setTimeout((() => ircServer.connect()), 30000); - }); -} diff --git a/packages/rocketchat-irc-server/server/irc-server-settings.js b/packages/rocketchat-irc-server/server/irc-server-settings.js deleted file mode 100644 index f52539f2d8d17..0000000000000 --- a/packages/rocketchat-irc-server/server/irc-server-settings.js +++ /dev/null @@ -1,51 +0,0 @@ -Meteor.startup(function() { - RocketChat.settings.addGroup('IRC_Server', function() { - this.add('IRC_Server_Enabled', false, { - type: 'boolean', - i18nLabel: 'Enabled', - i18nDescription: 'IRC_Server_Enabled' - }); - - this.add('IRC_Server_Host', '172.17.0.1', { - type: 'string', - i18nLabel: 'Host', - i18nDescription: 'IRC_Server_Host' - }); - - this.add('IRC_Server_Port', 7000, { - type: 'int', - i18nLabel: 'Port', - i18nDescription: 'IRC_Server_Port' - }); - - this.add('IRC_Server_Id', '97K', { - type: 'string', - i18nLabel: 'Id', - i18nDescription: 'IRC_Server_Id' - }); - - this.add('IRC_Server_Name', 'irc.example.com', { - type: 'string', - i18nLabel: 'Name', - i18nDescription: 'IRC_Server_Name' - }); - - this.add('IRC_Server_Description', 'Rocket.Chat IRC Server', { - type: 'string', - i18nLabel: 'Description', - i18nDescription: 'IRC_Server_Description' - }); - - this.add('IRC_Server_Send_Password', 'password', { - type: 'string', - i18nLabel: 'Send_Password', - i18nDescription: 'IRC_Server_Send_Password' - }); - - this.add('IRC_Server_Receive_Password', 'password', { - type: 'string', - i18nLabel: 'Receive_Password', - i18nDescription: 'IRC_Server_Receive_Password' - }); - }); -}); diff --git a/packages/rocketchat-irc-server/server/irc-server.js b/packages/rocketchat-irc-server/server/irc-server.js deleted file mode 100644 index 78707c299e4a1..0000000000000 --- a/packages/rocketchat-irc-server/server/irc-server.js +++ /dev/null @@ -1,929 +0,0 @@ -// TODO Refactoring - transfer IrcServer class (irc-server-bridge) to your specific file - -import net from 'net'; -import _ from 'underscore'; - -export class IrcServer { - constructor() { - this.ircPort = RocketChat.settings.get('IRC_Server_Port'); - this.ircHost = RocketChat.settings.get('IRC_Server_Host'); - this.serverId = RocketChat.settings.get('IRC_Server_Id'); - this.sendPassword = RocketChat.settings.get('IRC_Server_Send_Password'); - this.receivePassword = RocketChat.settings.get('IRC_Server_Receive_Password'); - this.serverName = RocketChat.settings.get('IRC_Server_Name'); - this.serverDescription = RocketChat.settings.get('IRC_Server_Description'); - - this.logCommands = true; - this.ircServers = {}; - this.ircUsers = {}; - this.localUsersById = {}; - this.localUsersByIrcId = {}; - this.nextUid = parseInt('a00001', 36); - - this.socket = new net.Socket; - this.socket.setNoDelay(); - this.socket.setEncoding('utf-8'); - this.socket.setKeepAlive(true); - this.socket.setTimeout(90000); - - this.socket.on('data', this.onReceiveRawMessage); - this.socket.on('close', this.onClose); - this.socket.on('timeout', this.onTimeout); - this.socket.on('error', this.onError); - - this.partialMessage = ''; - - this.state = 'waitingforconnection'; - } - - connect = () => { - console.log(`[irc-server] Attempting connection to IRC on ${ this.ircHost }:${ this.ircPort }`); - - this.socket.connect(this.ircPort, this.ircHost, this.onConnect); - - return this.state = 'connecting'; - } - - disconnect = () => { - this.socket.end(); - this.state = 'waitingforconnection'; - - return this.cleanup(); - } - - onConnect = () => { - this.writeCommand({ - command: 'PASS', - parameters: [this.sendPassword, 'TS', 6, this.serverId] // password, 'TS', TS version, SID - }); - - this.writeCommand({ - command: 'CAPAB', - trailer: 'TBURST EOB QS ENCAP EX CHW IE KNOCK' - }); - - this.writeCommand({ - command: 'SERVER', parameters: [this.serverName, 1], - trailer: this.serverDescription - }); - - return this.state = 'awaitingpass'; - } - - onClose = () => { - console.log('[irc-server] Socket closed, cleaning up state'); - - this.state = 'waitingforconnection'; - - return this.cleanup(); - } - - onTimeout = () => { - if (this.state === 'connected' || this.state === 'bursting') { - return this.writeCommand({ - command: 'PING', - trailer: this.serverId - }); - } else { - console.log('[irc-server] Timed out waiting for password'); - return this.disconnect(); - } - } - - onError = (error) => { - return console.log(`[irc-server] Socket error: ${ error.message }`); - } - - cleanup = () => { - this.partialMessage = ''; - - if (this.ircServers.length > 0) { - this.cleanupIrcServer(this.otherServerId); - } - - this.localUsersById = {}; - - return this.localUsersByIrcId = {}; - } - - burst = () => { - const users = RocketChat.models.Users.find({statusConnection: 'online'}, { fields: { _id: 1, username: 1, status: 1, name: 1}}).fetch(); - const rooms = RocketChat.models.Rooms.find({}, {fields: { ts: 1, name: 1, usernames: 1, t: 1 } }).fetch(); - - users.forEach(user => this.sendUser(user)); - rooms.forEach(room => this.sendRoom(room)); - - return this.writeCommand({ - command: 'EOB', - prefix: this.serverId - }); - } - - sendUser = (user) => { - const counterString = this.nextUid.toString().toUpperCase(); - - this.nextUid = this.nextUid + 1; - - const data = _.extend(user, {nickTimestamp: this.getTime(), ircUserId: `${ this.serverId }${ counterString }`}); - - this.localUsersById[data._id] = data; - this.localUsersByIrcId[data.ircUserId] = data; - - return this.writeCommand({ - prefix: this.serverId, - command: 'UID', - parameters: [user.username, 1, data.nickTimestamp, '+', user.username, this.serverName, this.ircHost, data.ircUserId, '*'], - trailer: user.name - }); - } - - sendRoom = (room) => { - if (room.t === 'd') { - return; - } - - const userIds = []; - // TODO It probably should to be limited by statusConnection equals 'online' - const subscribedUsers = RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { _id: 1, statusConnection: 1 } }).fetch(); - - subscribedUsers.forEach(user => { - if (user.statusConnection === 'online') { - return userIds.push(this.localUsersById[user._id].ircUserId); - } - }); - - const timestamp = Math.floor(room.ts.getTime() / 1000); - const nickSpace = 510 - 29 - room.name.length; - const nicksPerMessage = Math.floor(nickSpace / 20); - - let index = 0; - - const result = []; - - while ((index * nicksPerMessage) < userIds.length) { - this.writeCommand({ - prefix: this.serverId, - command: 'SJOIN', - parameters: [timestamp, `#${ room.name }`, '+nt'], - trailer: userIds.slice(index * nicksPerMessage, (index + 1) * nicksPerMessage).join(' ') - }); - - result.push(index = index + 1); - } - - return result; - } - - joinRoom = (user, room) => { - if (this.state !== 'connected') { - return; - } - - if (room.t === 'd' || this.localUsersById[user._id] === undefined) { - return; - } - - const userId = this.localUsersById[user._id].ircUserId; - const timestamp = Math.floor(room.ts.getTime() / 1000); - - return this.writeCommand({ - prefix: userId, - command: 'JOIN', - parameters: [timestamp, `#${ room.name }`, '+'] - }); - } - - loginUser = (user) => { - if (this.state !== 'connected' || this.localUsersById[user._id] !== undefined) { - return; - } - - this.sendUser(user); - - return RocketChat.models.Rooms.findWithUsername(user.username, {fields: { ts: 1, name: 1, t: 1 } }).forEach(room => this.joinRoom(user, room)); - } - - leaveRoom = (user, room) => { - if (this.state !== 'connected') { - return; - } - - if (room.t === 'd' || !this.localUsersById.includes(user._id)) { - return; - } - - const userId = this.localUsersById[user._id].ircUserId; - - return this.writeCommand({ - prefix: userId, - command: 'PART', - parameters: [`#${ room.name }`] - }); - } - - createRoom = (owner, room) => { - if (room.t === 'd' || this.localUsersById[owner._id] === undefined) { - return; - } - - return this.sendRoom(room); - } - - logoutUser = (user) => { - if (this.state !== 'connected' || !user || !user.id || !this.localUsersById.includes(user._id)) { - return; - } - - const userId = this.localUsersById[user._id].ircUserId; - - delete this.localUsersById[user._id]; - delete this.localUsersByIrcId[userId]; - - return this.writeCommand({ - prefix: userId, - command: 'PART', - trailer: 'Signed out' - }); - } - - sendMessage = (message, room) => { - if (this.state !== 'connected' || this.localUsersById[message.u._id] === undefined) { - return; - } - - const userId = this.localUsersById[message.u._id].ircUserId; - - const lines = message.msg.split('\n'); - - const result = []; - - lines.forEach(line => { - let messageSpace; - let target; - - line = line.trimRight(); - - if (room.t === 'd') { - messageSpace = 510 - 30; - - const targetUsername = _.find(room.usernames, username => username !== message.u.username); - const targetUser = _.find(this.ircUsers, user => user.username === targetUsername); - - target = targetUser.ircUserId; - } else { - //TODO: Should only send message if there are IRC users in the room - messageSpace = 510 - 22 - room.name.length; - target = `#${ room.name }`; - } - - let index = 0; - - while ((index * messageSpace) < line.length) { - this.writeCommand({ - prefix: userId, - command: 'PRIVMSG', - parameters: [target], - trailer: line.substring(index * messageSpace, (index + 1) * messageSpace) - }); - - result.push(index = index + 1); - } - }); - - return result; - } - - logoutIrcUser = (userId) => { - const user = this.ircUsers[userId]; - - Meteor.users.update({_id: user._id}, { - $set: { - status: 'offline' - } - }); - - RocketChat.models.Rooms.removeUsernameFromAll(user.username); - - return delete this.ircUsers[userId]; - } - - cleanupIrcServer = (serverId) => { - const disconnectedIds = []; - let queue = [serverId]; - - while (queue.length > 0) { - const id = queue.pop(); - disconnectedIds.push(id); - - queue = queue.concat(this.ircServers[id].proxiesServers); - - delete this.ircServers[id]; - } - - return _.filter(this.ircUsers, user => disconnectedIds.includes(user.connectedTo)).forEach(this.logoutIrcUser); - } - - getDirectRoom = (source, target) => { - const rid = [source._id, target._id].sort().join(''); - - RocketChat.models.Rooms.upsert({_id: rid}, { - $set: { - usernames: [source.username, target.username] - }, - $setOnInsert: { - t: 'd', - msgs: 0, - ts: new Date() - } - }); - - RocketChat.models.Subscriptions.upsert({rid, 'u._id': target._id}, { - $setOnInsert: { - name: source.username, - t: 'd', - open: false, - alert: false, - unread: 0, - u: { - _id: target._id, - username: target.username - } - } - }); - - return { - _id: rid, - t: 'd' - }; - } - - static getTime() { - return Math.floor(Date.now() / 1000); - } - - parseMessage = (command) => { - let currentIndex = 0; - let split; - - const result = {}; - - if (command.length === 0) { - return result; - } - - if (command[0] === ':') { - split = command.indexOf(' ', currentIndex); - - if (split === -1) { - currentIndex = command.length; - result.prefix = command.substring(1); - } else { - result.prefix = command.substring(currentIndex+1, split); - currentIndex = split + 1; - } - } - - if (currentIndex !== command.length) { - split = command.indexOf(' ', currentIndex); - - if (split === -1) { - result.command = command.substring(currentIndex); - currentIndex = command.length; - } else { - result.command = command.substring(currentIndex, split); - currentIndex = split + 1; - } - } - - result.parameters = []; - - while (currentIndex !== command.length && command[currentIndex] !== ':') { - split = command.indexOf(' ', currentIndex); - - if (split === -1) { - currentIndex = command.length; - result.parameters.push(command.substring(currentIndex)); - } else { - currentIndex = split + 1; - result.parameters.push(command.substring(currentIndex, split)); - } - } - - if (currentIndex !== command.length) { - result.trailer = command.substring(currentIndex + 1); - } - - return result; - } - - writeCommand = (command) => { - let buffer = command.prefix != null ? `:${ command.prefix } ` : ''; - buffer += command.command; - - if (command.parameters != null && command.parameters.length > 0) { - buffer += ` ${ command.parameters.join(' ') }`; - } - - if (command.trailer != null) { - buffer += ` :${ command.trailer }`; - } - - if (this.logCommands) { - console.log(`[irc-server] Sending Command: ${ buffer }`); - } - - return this.socket.write(`${ buffer }\r\n`); - }; - - static handleMalformed(command) { - return console.log(`[irc-server] Received invalid command: ${ command }`); - } - - onReceiveRawMessage = (data) => { - const dataString = data.toString(); - const lines = dataString.split('\r\n'); - - let newPartialMessage = ''; - if (dataString.substr(dataString.length - 2) !== '\n') { - newPartialMessage = lines.pop(); - } - - let firstLine = true; - - lines.forEach(line => { - line = line.trim(); - - if (firstLine) { - line = this.partialMessage + line; - firstLine = false; - } - - if (this.logCommands) { - console.log(`[irc-server] Received command: ${ line }`); - } - - const command = this.parseMessage(line); - - if (command && command.command != null) { - switch (this.state) { - case 'awaitingpass': - if (command.command === 'PASS') { - this.onReceivePASS(command); - } - break; - case 'bursting': - switch (command.command) { - case 'CAPAB': - this.onReceiveCAPAB(command); - break; - case 'SERVER': - this.onReceiveSERVER(command); - break; - case 'SVINFO': - this.onReceiveSVINFO(command); - break; - case 'UID': - this.onReceiveUID(command); - break; - case 'SID': - this.onReceiveSID(command); - break; - case 'SJOIN': - this.onReceiveSJOIN(command); - break; - case 'PING': - this.onReceivePING(command); - break; - case 'PONG': - this.onReceivePONG(command); - break; - case 'INVITE': - this.onReceiveINVITE(command); - break; - case 'KICK': - this.onReceiveKICK(command); - break; - } - break; - case 'connected': - switch (command.command) { - case 'PING': - this.onReceivePING(command); - break; - case 'PONG': - this.onReceivePONG(command); - break; - case 'EOB': - this.onReceiveEOB(command); - break; - case 'UID': - this.onReceiveUID(command); - break; - case 'SID': - this.onReceiveSID(command); - break; - case 'SJOIN': - this.onReceiveSJOIN(command); - break; - case 'SQUIT': - this.onReceiveSQUIT(command); - break; - case 'JOIN': - this.onReceiveJOIN(command); - break; - case 'PART': - this.onReceivePART(command); - break; - case 'QUIT': - this.onReceiveQUIT(command); - break; - case 'INVITE': - this.onReceiveINVITE(command); - break; - case 'KICK': - this.onReceiveKICK(command); - break; - case 'PRIVMSG': - this.onReceivePRIVMSG(command); - break; - } - break; - } - } - }); - - return this.partialMessage = newPartialMessage; - }; - - onReceivePASS = (command) => { - if (command.parameters.length !== 4) { - IrcServer.handleMalformed(command); - this.disconnect(); - return; - } - - const [password, protocol, protocolVersion, otherServerId] = command.parameters; - - this.otherServerId = otherServerId; - - if (password !== this.receivePassword) { - this.disconnect(); - return; - } - if (protocol !== 'TS' || protocolVersion !== '6') { - this.disconnect(); - return; - } - - this.ircServers[this.otherServerId] = {proxiesServers: []}; - return this.state = 'bursting'; - }; - - // eslint-disable-next-line no-unused-vars - onReceiveCAPAB = (command) => { - // TODO: Review it (search git history) - //return this.otherServerCapabilities = command.trailer.split(' '); - }; - - onReceiveSERVER = (command) => { - if (command.parameters.length !== 2 || command.trailer == null) { - IrcServer.handleMalformed(command); - this.disconnect(); - return; - } - - // eslint-disable-next-line no-unused-vars - const [serverName, hopCount] = command.parameters; - this.otherServerName = serverName; - - return this.ircServers[this.otherServerId].serverName = serverName; - }; - - onReceiveSVINFO = (command) => { - if (!command.parameters || command.parameters.length !== 3 || command.trailer == null) { - IrcServer.handleMalformed(command); - this.disconnect(); - return; - } - - // eslint-disable-next-line no-unused-vars - const [minTS, maxTS, discard] = command.parameters; - - // eslint-disable-next-line no-unused-vars - const timestamp = command.trailer; - - if (minTS > 6 || maxTS < 6) { - this.disconnect(); - return; - } - - console.log('[irc-server] Successfully connected to IRC server, starting to burst'); - - this.writeCommand({ - prefix: this.serverId, - command: 'SVINFO', - parameters: [6, 6, 0], - trailer: this.getTime() - }); - - this.burst(); - console.log('[irc-server] Finished bursting'); - - return this.state = 'connected'; - }; - - onReceiveSID = (command) => { - if (!command.parameters || command.parameters.length !== 3 || command.trailer == null || command.prefix == null) { - IrcServer.handleMalformed(command); - return; - } - - // eslint-disable-next-line no-unused-vars - const [serverName, hopCount, serverId] = command.parameters; - const connectedTo = command.prefix; - - // eslint-disable-next-line no-unused-vars - const serverDescription = command.trailer; - - this.ircServers[serverId] = {serverName, proxiesServers: []}; - this.ircServers[connectedTo].proxiesServers.push(serverId); - - return console.log(`[irc-server] New server connected: ${ serverName } via ${ this.ircServers[connectedTo].serverName }`); - }; - - onReceiveSJOIN = (command) => { - if (command.parameters.length !== 3 || command.trailer == null) { - IrcServer.handleMalformed(command); - return; - } - - // eslint-disable-next-line no-unused-vars - const [channelTimestamp, channel, mode] = command.parameters; - - const userIds = command.trailer.split(' '); - - const users = _.map(userIds, id => { - return { - username: this.ircUsers[id.substring(id.length-9)].username, - isOperator: id[0] === '@' - }; - - }); - - let room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - - if ((room == null)) { - const firstOperator = _.find(users, user => user.isOperator); - if (firstOperator == null) { - return; - } - - RocketChat.createRoom('c', channel.substring(1), firstOperator.username, [], false); - - room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - } - - return RocketChat.models.Rooms.addUsernamesById(room._id, _.map(users, user => user.username)); - } - - onReceiveUID = (command) => { - console.log('IRC command.parameters (onReceiveUID): ', command.parameters); - - if (command && command.parameters && command.parameters.length !== 9) { - IrcServer.handleMalformed(command); - return; - } - - // eslint-disable-next-line no-unused-vars - const [nick, hopCount, nickTimestamp, umodes, username, hostname, ipAddess, ircUserId, gecos] = command.parameters; - const connectedTo = command.prefix; - - //TODO Handle nick collisions - //TODO Handle verification that irc and rocketchat users are the same (send verification code to IRC user on IRC side) - - //TODO Handle modes - let user = RocketChat.models.Users.findOne({name: nick}); - - /** - Nick TS collisions: - If both users are to be collided, we must issue a KILL for the existing - user to all servers. If the new user has a UID then we must also issue a - KILL for that UID back to the server sending us data causing the collision. - - If only the existing user is being collided, we must issue a KILL for the - existing user to all servers except the server sending us data. If the - existing user has a UID and the server sending us data supports TS6 then - we must also issue a KILL for the existing users UID to the server sending - us data. - - If only the new user is being collided, we must issue a KILL for the new user - back to the server sending us data if the new user has a UID. - **/ - - if (!user) { - const userId = Meteor.call('registerUser', { - email: `${ nick }@${ hostname }`, - pass: '', - name: nick - }); - - RocketChat.models.Users.update({_id: userId}, { - $set: { - username: nick, - ircOnly: true - } - }); - - user = RocketChat.models.Users.findOne({_id: userId}); - } - - RocketChat.models.Users.update({_id: user._id}, { - $set: { - status: 'online' - } - }); - - user.nickTimestamp = nickTimestamp; - user.connectedTo = connectedTo; - user.ircUserId = ircUserId; - - this.ircUsers[ircUserId] = user; - - return console.log(`[irc-server] Registered user ${ nick } with ircUserId ${ ircUserId }`); - }; - - onReceivePING = (command) => { - const source = command.trailer; - - return this.writeCommand({ - prefix: this.serverId, - command: 'PONG', - parameters: [this.serverName], - trailer: source - }); - }; - - onReceivePONG = (command) => { - // eslint-disable-next-line no-unused-vars - let targetServerId; - - // eslint-disable-next-line no-unused-vars - const source = command.trailer; - - // eslint-disable-next-line no-unused-vars - const [sourceServerName] = command.parameters; - - return targetServerId = command.trailer; - }; - - onReceiveEOB = (command) => { - const serverId = command.prefix; - - return console.log(`[irc-server] Finished receiving burst from ${ this.ircServers[serverId].serverName }`); - }; - - onReceiveJOIN = (command) => { - const userId = command.prefix; - - // eslint-disable-next-line no-unused-vars - const [channelTimestamp, channel] = command.parameters; - - return RocketChat.models.Rooms.addUsernameByName(channel.substring(1), this.ircUsers[userId].username); - }; - - onReceivePART = (command) => { - const userId = command.prefix; - const [channel] = command.parameters; - - return RocketChat.models.Rooms.removeUsernameByName(channel.substring(1), this.ircUsers[userId].username); - }; - - onReceiveQUIT = (command) => { - const userId = command.prefix; - - // eslint-disable-next-line no-unused-vars - const reason = command.trailer; - - return this.logoutIrcUser(userId); - }; - - onReceiveINVITE = (command) => { - const invitingUserId = command.prefix; - - // eslint-disable-next-line no-unused-vars - const [invitedUserId, channel, channelTimestamp] = command.parameters; - - const invitingUser = this.ircUsers[invitingUserId]; - if (invitingUser == null) { - return; - } - - const invitedUser = this.localUsersByIrcId[invitedUserId]; - if (invitedUser == null) { - return; - } - - const room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - if (room == null) { - return; - } - - console.log(`[irc-server] Inviting ${ invitedUser.username } to ${ room.name }`); - - return Meteor.runAsUser(invitingUser._id, () => { - return Meteor.call('addUserToRoom', { - rid: room._id, - username: invitedUser.username - }); - }); - }; - - onReceiveKICK = (command) => { - const kickingUserId = command.prefix; - const [channel, kickedUserId] = command.parameters; - - const kickingUser = this.ircUsers[kickingUserId]; - if (kickingUser == null) { - return; - } - - const kickedUser = this.localUsersByIrcId[kickedUserId]; - if (kickedUser == null) { - return; - } - - const room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - if (room == null) { - return; - } - - console.log(`[irc-server] Kicking ${ kickedUser.username } from ${ room.name }`); - - return Meteor.runAsUser(kickingUser._id, () => { - return Meteor.call('removeUserFromRoom', { - rid: room._id, - username: kickedUser.username - }); - }); - }; - - onReceiveKILL = (command) => { - const ircUserId = command.prefix; - - console.log('IRC command.parameters: ', command.parameters); - - const userForKill = this.ircUsers[ircUserId]; - if (userForKill == null || userForKill._id == null) { - return; - } - - const killedUser = this.localUsersByIrcId[ircUserId]; - if (killedUser == null) { - return; - } - - console.log(`[irc-server] Killing ${ killedUser.username }`); - - return Meteor.runAsUser(userForKill._id, () => { - // TODO Kill user - }); - }; - - onReceiveSQUIT = (command) => { - let [targetServer] = command.parameters; - - // eslint-disable-next-line no-unused-vars - const comment = command.trailer; - - if (targetServer === this.serverId) { - targetServer = this.otherServerId; - } - - console.log(`[irc-server] IRC server disconnecting: ${ this.ircServers[targetServer].serverName }`); - return this.cleanupIrcServer(targetServer); - }; - - onReceivePRIVMSG = (command) => { - let room; - - const userId = command.prefix; - const [channel] = command.parameters; - const content = command.trailer; - const user = this.ircUsers[userId]; - - if (channel[0] === '#') { - room = RocketChat.models.Rooms.findOneByName(channel.substring(1)); - } else { - //TODO Handle direct messages - const targetUser = this.localUsersByIrcId[channel]; - room = this.getDirectRoom(user, targetUser); - } - - const message = { - msg: content, - ts: new Date() - }; - - return RocketChat.sendMessage(user, message, room); - } -} diff --git a/packages/rocketchat-irc/.npm/package/.gitignore b/packages/rocketchat-irc/.npm/package/.gitignore new file mode 100644 index 0000000000000..3c3629e647f5d --- /dev/null +++ b/packages/rocketchat-irc/.npm/package/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/packages/rocketchat-irc/.npm/package/README b/packages/rocketchat-irc/.npm/package/README new file mode 100644 index 0000000000000..3d492553a438e --- /dev/null +++ b/packages/rocketchat-irc/.npm/package/README @@ -0,0 +1,7 @@ +This directory and the files immediately inside it are automatically generated +when you change this package's NPM dependencies. Commit the files in this +directory (npm-shrinkwrap.json, .gitignore, and this README) to source control +so that others run the same versions of sub-dependencies. + +You should NOT check in the node_modules directory that Meteor automatically +creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/packages/rocketchat-irc/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-irc/.npm/package/npm-shrinkwrap.json new file mode 100644 index 0000000000000..f6941bfcae390 --- /dev/null +++ b/packages/rocketchat-irc/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,20 @@ +{ + "lockfileVersion": 1, + "dependencies": { + "dbly-linked-list": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dbly-linked-list/-/dbly-linked-list-0.2.0.tgz", + "integrity": "sha512-Ool7y15f6JRDs0YKx7Dh9uiTb1jS1SZLNdT3Y2q16DlaEghXbMsmODS/XittjR2xztt1gJUpz7jVxpqAPF8VGg==" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "queue-fifo": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/queue-fifo/-/queue-fifo-0.2.4.tgz", + "integrity": "sha512-o2xWptfzdw4QLIozUUcRPnppoTNK+X1DxWGd8csnJ1gQUsATfQaDryaGB1MhAu1L48vqPMtH69PZ1kZD82zlVw==" + } + } +} diff --git a/packages/rocketchat-irc/package.js b/packages/rocketchat-irc/package.js index 65378f796430a..d6429869544db 100644 --- a/packages/rocketchat-irc/package.js +++ b/packages/rocketchat-irc/package.js @@ -1,20 +1,21 @@ Package.describe({ name: 'rocketchat:irc', - version: '0.0.2', - summary: 'RocketChat libraries', + version: '0.0.1', + summary: 'RocketChat support for federating with IRC servers as a leaf node', git: '' }); -Package.onUse(function(api) { +Package.onUse(function (api) { api.use([ 'ecmascript', + 'underscore', 'rocketchat:lib' ]); - api.addFiles([ - 'server/settings.js', - 'server/server.js' - ], 'server'); + api.addFiles('server/irc.js', 'server'); + api.addFiles('server/irc-settings.js', 'server'); +}); - api.export(['Irc'], ['server']); +Npm.depends({ + 'queue-fifo': '0.2.4' }); diff --git a/packages/rocketchat-irc/server/irc-bridge/index.js b/packages/rocketchat-irc/server/irc-bridge/index.js new file mode 100644 index 0000000000000..1cb2b072afaf4 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/index.js @@ -0,0 +1,130 @@ +import _ from 'underscore' +import Queue from 'queue-fifo' + +import * as servers from '../servers' +import * as peerCommandHandlers from './peerHandlers' +import * as localCommandHandlers from './localHandlers' + +class Bridge { + constructor(config) { + // General + this.config = config + + // Workaround for Rocket.Chat callbacks being called multiple times + this.loggedInUsers = [] + + // Server + const Server = servers[this.config.server.protocol] + + this.server = new Server(this.config) + + this.setupPeerHandlers() + this.setupLocalHandlers() + + // Command queue + this.queue = new Queue() + this.queueTimeout = 5 + } + + init() { + this.server.register() + + this.server.on('registered', () => { + this.logQueue('Starting...') + + this.runQueue() + }) + } + + /** + * Log helper + */ + log(message) { + console.log(`[irc][bridge] ${message}`) + } + + logQueue(message) { + console.log(`[irc][bridge][queue] ${message}`) + } + + /** + * + * + * Queue + * + * + */ + onMessageReceived(from, command, ...parameters) { + this.queue.enqueue({ from, command, parameters }) + } + + async runQueue() { + // If it is empty, skip and keep the queue going + if(this.queue.isEmpty()) { + return setTimeout(this.runQueue.bind(this), this.queueTimeout) + } + + // Get the command + const item = this.queue.dequeue() + + this.logQueue(`Processing "${item.command}" command from "${item.from}"`) + + // Handle the command accordingly + switch(item.from) { + case 'local': + if (!localCommandHandlers[item.command]) throw new Error(`Could not find handler for local:${item.command}`) + + await localCommandHandlers[item.command].apply(this, item.parameters) + break + case 'peer': + if (!peerCommandHandlers[item.command]) throw new Error(`Could not find handler for peer:${item.command}`) + + await peerCommandHandlers[item.command].apply(this, item.parameters) + break + } + + // Keep the queue going + setTimeout(this.runQueue.bind(this), this.queueTimeout) + } + + /** + * + * + * Peer + * + * + */ + setupPeerHandlers() { + this.server.on('peerCommand', (cmd) => { + this.onMessageReceived('peer', cmd.identifier, cmd.args) + }) + } + + /** + * + * + * Local + * + * + */ + setupLocalHandlers() { + // Auth + RocketChat.callbacks.add('afterValidateLogin', this.onMessageReceived.bind(this, 'local', 'onLogin'), RocketChat.callbacks.priority.LOW, 'irc-on-login') + // Joining rooms or channels + RocketChat.callbacks.add('afterCreateChannel', this.onMessageReceived.bind(this, 'local', 'onCreateRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-create-channel') + RocketChat.callbacks.add('afterCreateRoom', this.onMessageReceived.bind(this, 'local', 'onCreateRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-create-room') + RocketChat.callbacks.add('afterJoinRoom', this.onMessageReceived.bind(this, 'local', 'onJoinRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-join-room') + // Leaving rooms or channels + RocketChat.callbacks.add('afterLeaveRoom', this.onMessageReceived.bind(this, 'local', 'onLeaveRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-leave-room') + // Chatting + RocketChat.callbacks.add('afterSaveMessage', this.onMessageReceived.bind(this, 'local', 'onSaveMessage'), RocketChat.callbacks.priority.LOW, 'irc-on-save-message') + // Leaving + RocketChat.callbacks.add('afterLogoutCleanUp', this.onMessageReceived.bind(this, 'local', 'onLogout'), RocketChat.callbacks.priority.LOW, 'irc-on-logout') + } + + sendCommand(command, parameters) { + this.server.emit('onReceiveFromLocal', command, parameters) + } +} + +export default Bridge diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js new file mode 100644 index 0000000000000..6d706b813486c --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js @@ -0,0 +1,6 @@ +export onCreateRoom from './onCreateRoom' +export onJoinRoom from './onJoinRoom' +export onLeaveRoom from './onLeaveRoom' +export onLogin from './onLogin' +export onLogout from './onLogout' +export onSaveMessage from './onSaveMessage' diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateRoom.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateRoom.js new file mode 100644 index 0000000000000..88e652f912e87 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateRoom.js @@ -0,0 +1,15 @@ +export default function handleOnCreateRoom(user, room) { + if (!room.usernames) { + return this.log(`Room ${room.name} does not have a valid list of usernames`) + } + + for (const username of room.usernames) { + const user = RocketChat.models.Users.findOne({ username }) + + if (user.profile.irc.fromIRC) { + this.sendCommand('joinChannel', { room, user }) + } else { + this.sendCommand('joinedChannel', { room, user }) + } + } +} diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onJoinRoom.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onJoinRoom.js new file mode 100644 index 0000000000000..0a4a14405f50a --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onJoinRoom.js @@ -0,0 +1,3 @@ +export default function handleOnJoinRoom(user, room) { + this.sendCommand('joinedChannel', { room, user }) +} diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLeaveRoom.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLeaveRoom.js new file mode 100644 index 0000000000000..ddf90f2462b57 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLeaveRoom.js @@ -0,0 +1,3 @@ +export default function handleOnLeaveRoom(user, room) { + this.sendCommand('leftChannel', { room, user }) +} diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js new file mode 100644 index 0000000000000..bfec2b8e15d95 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js @@ -0,0 +1,26 @@ +export default function handleOnLogin(login) { + if (login.user === null || this.loggedInUsers.indexOf(login.user._id) !== -1) { + return this.log('Invalid or duplicate handleOnLogin call') + } + + this.loggedInUsers.push(login.user._id) + + Meteor.users.update({ _id: login.user._id }, { + $set: { + 'profile.irc.fromIRC': false, + 'profile.irc.username': `${login.user.username}-rkt`, + 'profile.irc.nick': `${login.user.username}-rkt`, + 'profile.irc.hostname': 'rocket.chat' + } + }) + + const user = RocketChat.models.Users.findOne({ + _id: login.user._id + }) + + this.sendCommand('registerUser', user) + + const rooms = RocketChat.models.Rooms.findWithUsername(user.username).fetch() + + rooms.forEach(room => this.sendCommand('joinedChannel', { room, user })) +} diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogout.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogout.js new file mode 100644 index 0000000000000..c6a912774d956 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogout.js @@ -0,0 +1,5 @@ +export default function handleOnLogout(user) { + this.loggedInUsers = _.without(this.loggedInUsers, user._id) + + this.sendCommand('disconnected', { user }) +} diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js new file mode 100644 index 0000000000000..f6e09ed441dd5 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js @@ -0,0 +1,16 @@ +export default function handleOnSaveMessage(message, to) { + let toIdentification = '' + + // Direct message + if (to.t === 'd') { + const recipientUser = RocketChat.models.Users.findOne({ username: _.without(to.usernames, to.username)[0] }) + + toIdentification = recipientUser.profile.irc.nick + } else { + toIdentification = `#${to.name}` + } + + const user = RocketChat.models.Users.findOne({ _id: message.u._id }) + + this.sendCommand('sentMessage', { to: toIdentification, user, message: message.msg }) +} diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/disconnected.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/disconnected.js new file mode 100644 index 0000000000000..31a5ed5653db5 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/disconnected.js @@ -0,0 +1,13 @@ +export default function handleQUIT(args) { + let user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }) + + Meteor.users.update({ _id: user._id }, { + $set: { + status: 'offline' + } + }) + + RocketChat.models.Rooms.removeUsernameFromAll(user.username) +} diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/index.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/index.js new file mode 100644 index 0000000000000..2084cd70e5522 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/index.js @@ -0,0 +1,6 @@ +export disconnected from './disconnected' +export joinedChannel from './joinedChannel' +export leftChannel from './leftChannel' +export nickChanged from './nickChanged' +export sentMessage from './sentMessage' +export userRegistered from './userRegistered' diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js new file mode 100644 index 0000000000000..7a4f4dd6c4720 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js @@ -0,0 +1,22 @@ +export default function handleJoinedChannel(args) { + let user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }) + + if (!user) { + throw new Error(`Could not find a user with nick ${args.nick}`) + } + + let room = RocketChat.models.Rooms.findOneByName(args.roomName) + + if (!room) { + const createdRoom = RocketChat.createRoom('c', args.roomName, user.username, [ /* usernames of the participants here */]) + room = RocketChat.models.Rooms.findOne({ _id: createdRoom.rid }) + + this.log(`${user.username} created room ${args.roomName}`) + } else { + RocketChat.addUserToRoom(room._id, user) + + this.log(`${user.username} joined room ${room.name}`) + } +} diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/leftChannel.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/leftChannel.js new file mode 100644 index 0000000000000..09f84bdcba9ba --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/leftChannel.js @@ -0,0 +1,18 @@ +export default function handleLeftChannel(args) { + let user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }) + + if (!user) { + throw new Error(`Could not find a user with nick ${args.nick}`) + } + + let room = RocketChat.models.Rooms.findOneByName(args.roomName) + + if (!room) { + throw new Error(`Could not find a room with name ${args.roomName}`) + } + + this.log(`${user.username} left room ${room.name}`) + RocketChat.removeUserFromRoom(room._id, user) +} diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/nickChanged.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/nickChanged.js new file mode 100644 index 0000000000000..4c1e8eb76379a --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/nickChanged.js @@ -0,0 +1,19 @@ +export default function handleNickChanged(args) { + let user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }) + + if (!user) { + throw new Error(`Could not find an user with nick ${args.nick}`) + } + + this.log(`${user.username} changed nick: ${args.nick} -> ${args.newNick}`) + + // Update on the database + RocketChat.models.Users.update({ _id: user._id }, { + $set: { + name: args.newNick, + 'profile.irc.nick': args.newNick + } + }) +} diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js new file mode 100644 index 0000000000000..288e73a3d9a7f --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js @@ -0,0 +1,68 @@ +export default function handleSentMessage(args) { + let user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }) + + if (!user) { + throw new Error(`Could not find a user with nick ${args.nick}`) + } + + let room + + if (args.roomName) { + room = RocketChat.models.Rooms.findOneByName(args.roomName) + } else { + const recipientUser = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.recipientNick + }) + + room = getDirectRoom(user, recipientUser) + } + + const message = { + msg: args.message, + ts: new Date() + } + + RocketChat.sendMessage(user, message, room) +} + +/* + * + * Get direct chat room helper + * + * + */ +const getDirectRoom = (source, target) => { + const rid = [ source._id, target._id ].sort().join('') + + RocketChat.models.Rooms.upsert({ _id: rid }, { + $set: { + usernames: [source.username, target.username] + }, + $setOnInsert: { + t: 'd', + msgs: 0, + ts: new Date() + } + }) + + RocketChat.models.Subscriptions.upsert({rid, 'u._id': target._id}, { + $setOnInsert: { + name: source.username, + t: 'd', + open: false, + alert: false, + unread: 0, + u: { + _id: target._id, + username: target.username + } + } + }) + + return { + _id: rid, + t: 'd' + } +} diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/userRegistered.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/userRegistered.js new file mode 100644 index 0000000000000..d8b7ee6e1a32d --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/userRegistered.js @@ -0,0 +1,42 @@ +export default async function handleUserRegistered(args) { + // Check if there is an user with the given username + let user = RocketChat.models.Users.findOne({ + 'profile.irc.username': args.username + }) + + // If there is no user, create one... + if (!user) { + this.log(`Registering ${args.username} with nick: ${args.nick}`) + + const userToInsert = { + name: args.nick, + username: `${args.username}-irc`, + status: 'online', + utcOffset: 0, + active: true, + type: 'user', + profile: { + irc: { + fromIRC: true, + nick: args.nick, + username: args.username, + hostname: args.hostname + } + } + } + + user = RocketChat.models.Users.create(userToInsert) + } else { + // ...otherwise, log the user in and update the information + this.log(`Logging in ${args.username} with nick: ${args.nick}`) + + Meteor.users.update({ _id: user._id }, { + $set: { + status: 'online', + 'profile.irc.nick': args.nick, + 'profile.irc.username': args.username, + 'profile.irc.hostname': args.hostname, + } + }) + } +} diff --git a/packages/rocketchat-irc/server/irc-settings.js b/packages/rocketchat-irc/server/irc-settings.js new file mode 100644 index 0000000000000..740ee90f55c55 --- /dev/null +++ b/packages/rocketchat-irc/server/irc-settings.js @@ -0,0 +1,57 @@ +Meteor.startup(function () { + RocketChat.settings.addGroup('IRC', function () { + this.add('IRC_Enabled', false, { + type: 'boolean', + i18nLabel: 'Enabled', + i18nDescription: 'IRC_Enabled' + }) + + this.add('IRC_Protocol', 'RFC2813', { + type: 'select', + i18nLabel: 'Protocol', + i18nDescription: 'IRC_Protocol', + values: [ + { + key: 'RFC2813', + i18nLabel: 'RFC2813' + } + ] + }) + + this.add('IRC_Host', 'localhost', { + type: 'string', + i18nLabel: 'Host', + i18nDescription: 'IRC_Host' + }) + + this.add('IRC_Port', 6667, { + type: 'int', + i18nLabel: 'Port', + i18nDescription: 'IRC_Port' + }) + + this.add('IRC_Name', 'irc.rocket.chat', { + type: 'string', + i18nLabel: 'Name', + i18nDescription: 'IRC_Name' + }) + + this.add('IRC_Description', 'Rocket.Chat IRC Bridge', { + type: 'string', + i18nLabel: 'Description', + i18nDescription: 'IRC_Description' + }) + + this.add('IRC_Local_Password', 'password', { + type: 'string', + i18nLabel: 'Local_Password', + i18nDescription: 'IRC_Local_Password' + }) + + this.add('IRC_Peer_Password', 'password', { + type: 'string', + i18nLabel: 'Peer_Password', + i18nDescription: 'IRC_Peer_Password' + }) + }) +}) diff --git a/packages/rocketchat-irc/server/irc.js b/packages/rocketchat-irc/server/irc.js new file mode 100644 index 0000000000000..e6eea32a3205d --- /dev/null +++ b/packages/rocketchat-irc/server/irc.js @@ -0,0 +1,26 @@ +import _ from 'underscore'; + +import Bridge from './irc-bridge'; + +if (!!RocketChat.settings.get('IRC_Enabled') === true) { + // Normalize the config values + const config = { + server: { + protocol: RocketChat.settings.get('IRC_Protocol'), + host: RocketChat.settings.get('IRC_Host'), + port: RocketChat.settings.get('IRC_Port'), + name: RocketChat.settings.get('IRC_Name'), + description: RocketChat.settings.get('IRC_Description') + }, + passwords: { + local: RocketChat.settings.get('IRC_Local_Password'), + peer: RocketChat.settings.get('IRC_Peer_Password') + } + }; + + const bridge = new Bridge(config); + + Meteor.startup(() => { + bridge.init(); + }); +}; diff --git a/packages/rocketchat-irc/server/server.js b/packages/rocketchat-irc/server/server.js deleted file mode 100644 index bf3814f7f7b88..0000000000000 --- a/packages/rocketchat-irc/server/server.js +++ /dev/null @@ -1,439 +0,0 @@ -import _ from 'underscore'; -import net from 'net'; -import Lru from 'lru-cache'; - -/////// -// Assign values - -//Package availability -const IRC_AVAILABILITY = RocketChat.settings.get('IRC_Enabled'); - -// Cache prep -const MESSAGE_CACHE_SIZE = RocketChat.settings.get('IRC_Message_Cache_Size'); -const ircReceiveMessageCache = Lru(MESSAGE_CACHE_SIZE);//eslint-disable-line -const ircSendMessageCache = Lru(MESSAGE_CACHE_SIZE);//eslint-disable-line - -// IRC server -const IRC_PORT = RocketChat.settings.get('IRC_Port'); -const IRC_HOST = RocketChat.settings.get('IRC_Host'); - -const ircClientMap = {}; - -////// -// Core functionality - -const bind = function(f) { - const g = Meteor.bindEnvironment((self, ...args) => f.apply(self, args)); - return function(...args) { g(this, ...args); }; -}; - -const async = (f, ...args) => Meteor.wrapAsync(f)(...args); - -class IrcClient { - constructor(loginReq) { - this.loginReq = loginReq; - - this.user = this.loginReq.user; - ircClientMap[this.user._id] = this; - this.ircPort = IRC_PORT; - this.ircHost = IRC_HOST; - this.msgBuf = []; - - this.isConnected = false; - this.isDistroyed = false; - this.socket = new net.Socket; - this.socket.setNoDelay; - this.socket.setEncoding('utf-8'); - this.socket.setKeepAlive(true); - this.connect = this.connect.bind(this); - this.onConnect = this.onConnect.bind(this); - this.onConnect = bind(this.onConnect); - this.onClose = bind(this.onClose); - this.onTimeout = bind(this.onTimeout); - this.onError = bind(this.onError); - this.onReceiveRawMessage = this.onReceiveRawMessage.bind(this); - this.onReceiveRawMessage = bind(this.onReceiveRawMessage); - this.socket.on('data', this.onReceiveRawMessage); - this.socket.on('close', this.onClose); - this.socket.on('timeout', this.onTimeout); - this.socket.on('error', this.onError); - - this.isJoiningRoom = false; - this.receiveMemberListBuf = {}; - this.pendingJoinRoomBuf = []; - - this.successLoginMessageRegex = new RegExp(RocketChat.settings.get('IRC_RegEx_successLogin')); - this.failedLoginMessageRegex = new RegExp(RocketChat.settings.get('IRC_RegEx_failedLogin')); - this.receiveMessageRegex = new RegExp(RocketChat.settings.get('IRC_RegEx_receiveMessage')); - this.receiveMemberListRegex = new RegExp(RocketChat.settings.get('IRC_RegEx_receiveMemberList')); - this.endMemberListRegex = new RegExp(RocketChat.settings.get('IRC_RegEx_endMemberList')); - this.addMemberToRoomRegex = new RegExp(RocketChat.settings.get('IRC_RegEx_addMemberToRoom')); - this.removeMemberFromRoomRegex = new RegExp(RocketChat.settings.get('IRC_RegEx_removeMemberFromRoom')); - this.quitMemberRegex = new RegExp(RocketChat.settings.get('IRC_RegEx_quitMember')); - } - - connect(loginCb) { - this.loginCb = loginCb; - this.socket.connect(this.ircPort, this.ircHost, this.onConnect); - this.initRoomList(); - } - - disconnect() { - this.isDistroyed = true; - this.socket.destroy(); - } - - onConnect() { - console.log('[irc] onConnect -> '.yellow, this.user.username, 'connect success.'); - this.socket.write(`NICK ${ this.user.username }\r\n`); - this.socket.write(`USER ${ this.user.username } 0 * :${ this.user.name }\r\n`); - // message order could not make sure here - this.isConnected = true; - const messageBuf = this.msgBuf; - messageBuf.forEach(msg => this.socket.write(msg)); - } - - onClose() { - console.log('[irc] onClose -> '.yellow, this.user.username, 'connection close.'); - this.isConnected = false; - if (this.isDistroyed) { - delete ircClientMap[this.user._id]; - } else { - this.connect(); - } - } - - onTimeout() { - console.log('[irc] onTimeout -> '.yellow, this.user.username, 'connection timeout.', arguments); - } - - onError() { - console.log('[irc] onError -> '.yellow, this.user.username, 'connection error.', arguments); - } - - onReceiveRawMessage(data) { - data = data.toString().split('\n'); - - data.forEach(line => { - line = line.trim(); - console.log(`[${ this.ircHost }:${ this.ircPort }]:`, line); - - // Send heartbeat package to irc server - if (line.indexOf('PING') === 0) { - this.socket.write(line.replace('PING :', 'PONG ')); - return; - } - let matchResult = this.receiveMessageRegex.exec(line); - if (matchResult) { - this.onReceiveMessage(matchResult[1], matchResult[2], matchResult[3]); - return; - } - matchResult = this.receiveMemberListRegex.exec(line); - if (matchResult) { - this.onReceiveMemberList(matchResult[1], matchResult[2].split(' ')); - return; - } - matchResult = this.endMemberListRegex.exec(line); - if (matchResult) { - this.onEndMemberList(matchResult[1]); - return; - } - matchResult = this.addMemberToRoomRegex.exec(line); - if (matchResult) { - this.onAddMemberToRoom(matchResult[1], matchResult[2]); - return; - } - matchResult = this.removeMemberFromRoomRegex.exec(line); - if (matchResult) { - this.onRemoveMemberFromRoom(matchResult[1], matchResult[2]); - return; - } - matchResult = this.quitMemberRegex.exec(line); - if (matchResult) { - this.onQuitMember(matchResult[1]); - return; - } - matchResult = this.successLoginMessageRegex.exec(line); - if (matchResult) { - this.onSuccessLoginMessage(); - return; - } - matchResult = this.failedLoginMessageRegex.exec(line); - if (matchResult) { - this.onFailedLoginMessage(); - return; - } - }); - } - - onSuccessLoginMessage() { - console.log('[irc] onSuccessLoginMessage -> '.yellow); - if (this.loginCb) { - this.loginCb(null, this.loginReq); - } - } - - onFailedLoginMessage() { - console.log('[irc] onFailedLoginMessage -> '.yellow); - this.loginReq.allowed = false; - this.disconnect(); - if (this.loginCb) { - this.loginCb(null, this.loginReq); - } - } - - onReceiveMessage(source, target, content) { - const now = new Date; - const timestamp = now.getTime(); - let 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 = this.createUserWhenNotExist(source); - let room; - if (target[0] === '#') { - room = RocketChat.models.Rooms.findOneByName(target.substring(1)); - } else { - room = this.createDirectRoomWhenNotExist(source, this.user); - } - const 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) { - this.receiveMemberListBuf[roomName] = this.receiveMemberListBuf[roomName].concat(members); - } - - onEndMemberList(roomName) { - const newMembers = this.receiveMemberListBuf[roomName]; - console.log('[irc] onEndMemberList -> '.yellow, 'room:', roomName, 'members:', newMembers.join(',')); - const room = RocketChat.models.Rooms.findOneByNameAndType(roomName, 'c'); - if (!room) { - return; - } - const oldMembers = room.usernames; - const appendMembers = _.difference(newMembers, oldMembers); - const removeMembers = _.difference(oldMembers, newMembers); - appendMembers.forEach(member => this.createUserWhenNotExist(member)); - RocketChat.models.Rooms.removeUsernamesById(room._id, removeMembers); - RocketChat.models.Rooms.addUsernamesById(room._id, appendMembers); - - this.isJoiningRoom = false; - roomName = this.pendingJoinRoomBuf.shift(); - if (roomName) { - this.joinRoom({ - t: 'c', - name: roomName - }); - } - } - - sendRawMessage(msg) { - console.log('[irc] sendRawMessage -> '.yellow, msg.slice(0, -2)); - if (this.isConnected) { - this.socket.write(msg); - } else { - this.msgBuf.push(msg); - } - } - - sendMessage(room, message) { - console.log('[irc] sendMessage -> '.yellow, 'userName:', message.u.username); - let target = ''; - if (room.t === 'c') { - target = `#${ room.name }`; - } else if (room.t === 'd') { - const usernames = room.usernames; - usernames.forEach(name => { - if (message.u.username !== name) { - target = name; - return; - } - }); - } - const cacheKey = [this.user.username, target, message.msg].join(','); - console.log('[irc] ircSendMessageCache.set -> '.yellow, 'key:', cacheKey, 'ts:', message.ts.getTime()); - ircSendMessageCache.set(cacheKey, message.ts.getTime()); - const msg = `PRIVMSG ${ target } :${ message.msg }\r\n`; - this.sendRawMessage(msg); - } - - initRoomList() { - const roomsCursor = RocketChat.models.Rooms.findByTypeContainingUsername('c', this.user.username, { fields: { name: 1, t: 1 }}); - const rooms = roomsCursor.fetch(); - rooms.forEach(room => this.joinRoom(room)); - } - - joinRoom(room) { - if (room.t !== 'c' || room.name === 'general') { - return; - } - if (this.isJoiningRoom) { - return this.pendingJoinRoomBuf.push(room.name); - } - console.log('[irc] joinRoom -> '.yellow, 'roomName:', room.name, 'pendingJoinRoomBuf:', this.pendingJoinRoomBuf.join(',')); - const msg = `JOIN #${ room.name }\r\n`; - this.receiveMemberListBuf[room.name] = []; - this.sendRawMessage(msg); - this.isJoiningRoom = true; - } - - leaveRoom(room) { - if (room.t !== 'c') { - return; - } - const msg = `PART #${ room.name }\r\n`; - this.sendRawMessage(msg); - } - - getMemberList(room) { - if (room.t !== 'c') { - return; - } - const msg = `NAMES #${ room.name }\r\n`; - this.receiveMemberListBuf[room.name] = []; - this.sendRawMessage(msg); - } - - onAddMemberToRoom(member, roomName) { - if (this.user.username === member) { - return; - } - console.log('[irc] onAddMemberToRoom -> '.yellow, 'roomName:', roomName, 'member:', member); - this.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); - } - - onQuitMember(member) { - console.log('[irc] onQuitMember ->'.yellow, 'username:', member); - RocketChat.models.Rooms.removeUsernameFromAll(member); - Meteor.users.update({ name: member }, { $set: { status: 'offline' }}); - } - - createUserWhenNotExist(name) { - const user = Meteor.users.findOne({ name }); - if (user) { - return user; - } - console.log('[irc] createNotExistUser ->'.yellow, 'userName:', name); - Meteor.call('registerUser', { - email: `${ name }@rocketchat.org`, - pass: 'rocketchat', - name - }); - Meteor.users.update({ name }, { - $set: { - status: 'online', - username: name - } - }); - return Meteor.users.findOne({ name }); - } - - createDirectRoomWhenNotExist(source, target) { - console.log('[irc] createDirectRoomWhenNotExist -> '.yellow, 'source:', source, 'target:', target); - const rid = [source._id, target._id].sort().join(''); - const 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, $and: [{ 'u._id': target._id}]}, { - $setOnInsert: { - name: source.username, - t: 'd', - open: false, - alert: false, - unread: 0, - userMentions: 0, - groupMentions: 0, - u: { _id: target._id, username: target.username }} - }); - return { t: 'd', _id: rid }; - } -} - -IrcClient.getByUid = function(uid) { - return ircClientMap[uid]; -}; - -IrcClient.create = function(login) { - if (login.user == null) { - return login; - } - if (!(login.user._id in ircClientMap)) { - const ircClient = new IrcClient(login); - return async(ircClient.connect); - } - return login; -}; - -function IrcLoginer(login) { - console.log('[irc] validateLogin -> '.yellow, login); - return IrcClient.create(login); -} - - -function IrcSender(message) { - const name = message.u.username; - const timestamp = message.ts.getTime(); - const cacheKey = `${ name }${ timestamp }`; - if (ircReceiveMessageCache.get(cacheKey)) { - return message; - } - const room = RocketChat.models.Rooms.findOneById(message.rid, { fields: { name: 1, usernames: 1, t: 1 }}); - const ircClient = IrcClient.getByUid(message.u._id); - ircClient.sendMessage(room, message); - return message; -} - - -function IrcRoomJoiner(user, room) { - const ircClient = IrcClient.getByUid(user._id); - ircClient.joinRoom(room); - return room; -} - - -function IrcRoomLeaver(user, room) { - const ircClient = IrcClient.getByUid(user._id); - ircClient.leaveRoom(room); - return room; -} - -function IrcLogoutCleanUper(user) { - const ircClient = IrcClient.getByUid(user._id); - ircClient.disconnect(); - return user; -} - -////// -// Make magic happen - -// Only proceed if the package has been enabled -if (IRC_AVAILABILITY === true) { - RocketChat.callbacks.add('beforeValidateLogin', IrcLoginer, RocketChat.callbacks.priority.LOW, 'irc-loginer'); - RocketChat.callbacks.add('beforeSaveMessage', IrcSender, RocketChat.callbacks.priority.LOW, 'irc-sender'); - RocketChat.callbacks.add('beforeJoinRoom', IrcRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-room-joiner'); - RocketChat.callbacks.add('beforeCreateChannel', IrcRoomJoiner, RocketChat.callbacks.priority.LOW, 'irc-room-joiner-create-channel'); - RocketChat.callbacks.add('beforeLeaveRoom', IrcRoomLeaver, RocketChat.callbacks.priority.LOW, 'irc-room-leaver'); - RocketChat.callbacks.add('afterLogoutCleanUp', IrcLogoutCleanUper, RocketChat.callbacks.priority.LOW, 'irc-clean-up'); -} diff --git a/packages/rocketchat-irc/server/servers/RFC2813/codes.js b/packages/rocketchat-irc/server/servers/RFC2813/codes.js new file mode 100644 index 0000000000000..717ea674047ce --- /dev/null +++ b/packages/rocketchat-irc/server/servers/RFC2813/codes.js @@ -0,0 +1,519 @@ +/** + * This file is part of https://github.com/martynsmith/node-irc + * by https://github.com/martynsmith + */ + +module.exports = { + '001': { + name: 'rpl_welcome', + type: 'reply' + }, + '002': { + name: 'rpl_yourhost', + type: 'reply' + }, + '003': { + name: 'rpl_created', + type: 'reply' + }, + '004': { + name: 'rpl_myinfo', + type: 'reply' + }, + '005': { + name: 'rpl_isupport', + type: 'reply' + }, + 200: { + name: 'rpl_tracelink', + type: 'reply' + }, + 201: { + name: 'rpl_traceconnecting', + type: 'reply' + }, + 202: { + name: 'rpl_tracehandshake', + type: 'reply' + }, + 203: { + name: 'rpl_traceunknown', + type: 'reply' + }, + 204: { + name: 'rpl_traceoperator', + type: 'reply' + }, + 205: { + name: 'rpl_traceuser', + type: 'reply' + }, + 206: { + name: 'rpl_traceserver', + type: 'reply' + }, + 208: { + name: 'rpl_tracenewtype', + type: 'reply' + }, + 211: { + name: 'rpl_statslinkinfo', + type: 'reply' + }, + 212: { + name: 'rpl_statscommands', + type: 'reply' + }, + 213: { + name: 'rpl_statscline', + type: 'reply' + }, + 214: { + name: 'rpl_statsnline', + type: 'reply' + }, + 215: { + name: 'rpl_statsiline', + type: 'reply' + }, + 216: { + name: 'rpl_statskline', + type: 'reply' + }, + 218: { + name: 'rpl_statsyline', + type: 'reply' + }, + 219: { + name: 'rpl_endofstats', + type: 'reply' + }, + 221: { + name: 'rpl_umodeis', + type: 'reply' + }, + 241: { + name: 'rpl_statslline', + type: 'reply' + }, + 242: { + name: 'rpl_statsuptime', + type: 'reply' + }, + 243: { + name: 'rpl_statsoline', + type: 'reply' + }, + 244: { + name: 'rpl_statshline', + type: 'reply' + }, + 250: { + name: 'rpl_statsconn', + type: 'reply' + }, + 251: { + name: 'rpl_luserclient', + type: 'reply' + }, + 252: { + name: 'rpl_luserop', + type: 'reply' + }, + 253: { + name: 'rpl_luserunknown', + type: 'reply' + }, + 254: { + name: 'rpl_luserchannels', + type: 'reply' + }, + 255: { + name: 'rpl_luserme', + type: 'reply' + }, + 256: { + name: 'rpl_adminme', + type: 'reply' + }, + 257: { + name: 'rpl_adminloc1', + type: 'reply' + }, + 258: { + name: 'rpl_adminloc2', + type: 'reply' + }, + 259: { + name: 'rpl_adminemail', + type: 'reply' + }, + 261: { + name: 'rpl_tracelog', + type: 'reply' + }, + 265: { + name: 'rpl_localusers', + type: 'reply' + }, + 266: { + name: 'rpl_globalusers', + type: 'reply' + }, + 300: { + name: 'rpl_none', + type: 'reply' + }, + 301: { + name: 'rpl_away', + type: 'reply' + }, + 302: { + name: 'rpl_userhost', + type: 'reply' + }, + 303: { + name: 'rpl_ison', + type: 'reply' + }, + 305: { + name: 'rpl_unaway', + type: 'reply' + }, + 306: { + name: 'rpl_nowaway', + type: 'reply' + }, + 311: { + name: 'rpl_whoisuser', + type: 'reply' + }, + 312: { + name: 'rpl_whoisserver', + type: 'reply' + }, + 313: { + name: 'rpl_whoisoperator', + type: 'reply' + }, + 314: { + name: 'rpl_whowasuser', + type: 'reply' + }, + 315: { + name: 'rpl_endofwho', + type: 'reply' + }, + 317: { + name: 'rpl_whoisidle', + type: 'reply' + }, + 318: { + name: 'rpl_endofwhois', + type: 'reply' + }, + 319: { + name: 'rpl_whoischannels', + type: 'reply' + }, + 321: { + name: 'rpl_liststart', + type: 'reply' + }, + 322: { + name: 'rpl_list', + type: 'reply' + }, + 323: { + name: 'rpl_listend', + type: 'reply' + }, + 324: { + name: 'rpl_channelmodeis', + type: 'reply' + }, + 329: { + name: 'rpl_creationtime', + type: 'reply' + }, + 331: { + name: 'rpl_notopic', + type: 'reply' + }, + 332: { + name: 'rpl_topic', + type: 'reply' + }, + 333: { + name: 'rpl_topicwhotime', + type: 'reply' + }, + 341: { + name: 'rpl_inviting', + type: 'reply' + }, + 342: { + name: 'rpl_summoning', + type: 'reply' + }, + 351: { + name: 'rpl_version', + type: 'reply' + }, + 352: { + name: 'rpl_whoreply', + type: 'reply' + }, + 353: { + name: 'rpl_namreply', + type: 'reply' + }, + 364: { + name: 'rpl_links', + type: 'reply' + }, + 365: { + name: 'rpl_endoflinks', + type: 'reply' + }, + 366: { + name: 'rpl_endofnames', + type: 'reply' + }, + 367: { + name: 'rpl_banlist', + type: 'reply' + }, + 368: { + name: 'rpl_endofbanlist', + type: 'reply' + }, + 369: { + name: 'rpl_endofwhowas', + type: 'reply' + }, + 371: { + name: 'rpl_info', + type: 'reply' + }, + 372: { + name: 'rpl_motd', + type: 'reply' + }, + 374: { + name: 'rpl_endofinfo', + type: 'reply' + }, + 375: { + name: 'rpl_motdstart', + type: 'reply' + }, + 376: { + name: 'rpl_endofmotd', + type: 'reply' + }, + 381: { + name: 'rpl_youreoper', + type: 'reply' + }, + 382: { + name: 'rpl_rehashing', + type: 'reply' + }, + 391: { + name: 'rpl_time', + type: 'reply' + }, + 392: { + name: 'rpl_usersstart', + type: 'reply' + }, + 393: { + name: 'rpl_users', + type: 'reply' + }, + 394: { + name: 'rpl_endofusers', + type: 'reply' + }, + 395: { + name: 'rpl_nousers', + type: 'reply' + }, + 401: { + name: 'err_nosuchnick', + type: 'error' + }, + 402: { + name: 'err_nosuchserver', + type: 'error' + }, + 403: { + name: 'err_nosuchchannel', + type: 'error' + }, + 404: { + name: 'err_cannotsendtochan', + type: 'error' + }, + 405: { + name: 'err_toomanychannels', + type: 'error' + }, + 406: { + name: 'err_wasnosuchnick', + type: 'error' + }, + 407: { + name: 'err_toomanytargets', + type: 'error' + }, + 409: { + name: 'err_noorigin', + type: 'error' + }, + 411: { + name: 'err_norecipient', + type: 'error' + }, + 412: { + name: 'err_notexttosend', + type: 'error' + }, + 413: { + name: 'err_notoplevel', + type: 'error' + }, + 414: { + name: 'err_wildtoplevel', + type: 'error' + }, + 421: { + name: 'err_unknowncommand', + type: 'error' + }, + 422: { + name: 'err_nomotd', + type: 'error' + }, + 423: { + name: 'err_noadmininfo', + type: 'error' + }, + 424: { + name: 'err_fileerror', + type: 'error' + }, + 431: { + name: 'err_nonicknamegiven', + type: 'error' + }, + 432: { + name: 'err_erroneusnickname', + type: 'error' + }, + 433: { + name: 'err_nicknameinuse', + type: 'error' + }, + 436: { + name: 'err_nickcollision', + type: 'error' + }, + 441: { + name: 'err_usernotinchannel', + type: 'error' + }, + 442: { + name: 'err_notonchannel', + type: 'error' + }, + 443: { + name: 'err_useronchannel', + type: 'error' + }, + 444: { + name: 'err_nologin', + type: 'error' + }, + 445: { + name: 'err_summondisabled', + type: 'error' + }, + 446: { + name: 'err_usersdisabled', + type: 'error' + }, + 451: { + name: 'err_notregistered', + type: 'error' + }, + 461: { + name: 'err_needmoreparams', + type: 'error' + }, + 462: { + name: 'err_alreadyregistred', + type: 'error' + }, + 463: { + name: 'err_nopermforhost', + type: 'error' + }, + 464: { + name: 'err_passwdmismatch', + type: 'error' + }, + 465: { + name: 'err_yourebannedcreep', + type: 'error' + }, + 467: { + name: 'err_keyset', + type: 'error' + }, + 471: { + name: 'err_channelisfull', + type: 'error' + }, + 472: { + name: 'err_unknownmode', + type: 'error' + }, + 473: { + name: 'err_inviteonlychan', + type: 'error' + }, + 474: { + name: 'err_bannedfromchan', + type: 'error' + }, + 475: { + name: 'err_badchannelkey', + type: 'error' + }, + 481: { + name: 'err_noprivileges', + type: 'error' + }, + 482: { + name: 'err_chanoprivsneeded', + type: 'error' + }, + 483: { + name: 'err_cantkillserver', + type: 'error' + }, + 491: { + name: 'err_nooperhost', + type: 'error' + }, + 501: { + name: 'err_umodeunknownflag', + type: 'error' + }, + 502: { + name: 'err_usersdontmatch', + type: 'error' + } +}; diff --git a/packages/rocketchat-irc/server/servers/RFC2813/index.js b/packages/rocketchat-irc/server/servers/RFC2813/index.js new file mode 100644 index 0000000000000..232bfbbed3c62 --- /dev/null +++ b/packages/rocketchat-irc/server/servers/RFC2813/index.js @@ -0,0 +1,162 @@ +import _ from 'underscore' +import net from 'net' +import util from 'util' +import { EventEmitter } from 'events' + +import parseMessage from './parseMessage' + +import peerCommandHandlers from './peerCommandHandlers' +import localCommandHandlers from './localCommandHandlers' + +class RFC2813 { + constructor(config) { + this.config = config + + // Hold registered state + this.registerSteps = [] + this.isRegistered = false + + // Hold peer server information + this.serverPrefix = null + + // Hold the buffer while receiving + this.receiveBuffer = new Buffer('') + + // Setup socket + this.socket = new net.Socket() + this.socket.setNoDelay() + this.socket.setEncoding('utf-8') + this.socket.setKeepAlive(true) + this.socket.setTimeout(90000) + + this.socket.on('data', this.onReceiveFromPeer.bind(this)) + // this.socket.on('close', this.onClose) + // this.socket.on('timeout', this.onTimeout) + // this.socket.on('error', this.onError) + + this.socket.on('connect', this.onConnect.bind(this)) + this.socket.on('error', (err) => console.log(`[irc][server][err]`, err)) + + // Setup local + this.on('onReceiveFromLocal', this.onReceiveFromLocal.bind(this)) + } + + /** + * Log helper + */ + log(message) { + console.log(`[irc][server] ${message}`) + } + + /** + * Connect + */ + register() { + this.log(`Connecting to @${this.config.server.host}:${this.config.server.port}`) + + this.socket.connect(this.config.server.port, this.config.server.host) + } + + /** + * Setup the server connection + */ + onConnect() { + this.log('Connected! Registering as server...') + + this.write({ + command: 'PASS', + parameters: [ this.config.passwords.local, '0210', 'ngircd' ] + }) + + this.write({ + command: 'SERVER', parameters: [ this.config.server.name ], + trailer: this.config.server.description + }) + } + + /** + * Sends a command message through the socket + */ + write(command) { + let buffer = command.prefix ? `:${command.prefix} ` : '' + buffer += command.command + + if (command.parameters && command.parameters.length > 0) { + buffer += ` ${command.parameters.join(' ')}` + } + + if (command.trailer) { + buffer += ` :${command.trailer}` + } + + this.log(`Sending Command: ${buffer}`) + + return this.socket.write(`${buffer}\r\n`) + } + + /** + * + * + * Peer message handling + * + * + */ + onReceiveFromPeer(chunk) { + if (typeof (chunk) === 'string') { + this.receiveBuffer += chunk + } else { + this.receiveBuffer = Buffer.concat([this.receiveBuffer, chunk]) + } + + var lines = this.receiveBuffer.toString().split(new RegExp('\r\n|\r|\n')) + + // If the buffer does not end with \r\n, more chunks are coming + if (lines.pop()) return + + // Reset the buffer + this.receiveBuffer = new Buffer('') + + lines.forEach((line) => { + if (line.length) { + var parsedMessage = parseMessage(line) + + if (peerCommandHandlers[parsedMessage.command]) { + this.log(`Handling peer message: ${line}`) + + const command = peerCommandHandlers[parsedMessage.command].call(this, parsedMessage) + + if (command) { + this.log(`Emitting peer command to local: ${JSON.stringify(command)}`) + + this.emit('peerCommand', command) + } + + } else { + this.log(`Unhandled peer message: ${JSON.stringify(parsedMessage)}`) + } + } + }) + } + + /** + * + * + * Local message handling + * + * + */ + onReceiveFromLocal(command, parameters) { + if (localCommandHandlers[command]) { + this.log(`Handling local command: ${command}`) + + localCommandHandlers[command].call(this, parameters) + + } else { + this.log(`Unhandled local command: ${JSON.stringify(command)}`) + } + } +} + +util.inherits(RFC2813, EventEmitter) + +export default RFC2813 diff --git a/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js b/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js new file mode 100644 index 0000000000000..7a5ca783e0b93 --- /dev/null +++ b/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js @@ -0,0 +1,74 @@ +export default { + registerUser: function (parameters) { + const { name, profile: { irc: { nick, username } } } = parameters + + this.write({ + prefix: this.config.server.name, + command: 'NICK', parameters: [ nick, 1, username, 'irc.rocket.chat', 1, '+i' ], + trailer: name + }) + }, + + joinChannel: function (parameters) { + const { + room: { name: roomName }, + user: { profile: { irc: { nick } } } + } = parameters + + this.write({ + prefix: this.config.server.name, + command: 'NJOIN', parameters: [ `#${roomName}` ], + trailer: nick + }) + }, + + joinedChannel: function (parameters) { + const { + room: { name: roomName }, + user: { profile: { irc: { nick } } } + } = parameters + + this.write({ + prefix: nick, + command: 'JOIN', parameters: [ `#${roomName}` ] + }) + }, + + leftChannel: function (parameters) { + const { + room: { name: roomName }, + user: { profile: { irc: { nick } } } + } = parameters + + this.write({ + prefix: nick, + command: 'PART', parameters: [ `#${roomName}` ] + }) + }, + + sentMessage: function (parameters) { + const { + user: { profile: { irc: { nick } } }, + to, + message + } = parameters + + this.write({ + prefix: nick, + command: 'PRIVMSG', parameters: [ to ], + trailer: message + }) + }, + + disconnected: function (parameters) { + const { + user: { profile: { irc: { nick } } } + } = parameters + + this.write({ + prefix: nick, + command: 'QUIT' + }) + } + +} diff --git a/packages/rocketchat-irc/server/servers/RFC2813/parseMessage.js b/packages/rocketchat-irc/server/servers/RFC2813/parseMessage.js new file mode 100644 index 0000000000000..9c39709512eae --- /dev/null +++ b/packages/rocketchat-irc/server/servers/RFC2813/parseMessage.js @@ -0,0 +1,68 @@ +/** + * This file is part of https://github.com/martynsmith/node-irc + * by https://github.com/martynsmith + */ + +var replyFor = require('./codes'); + +/** + * parseMessage(line, stripColors) + * + * takes a raw "line" from the IRC server and turns it into an object with + * useful keys + * @param {String} line Raw message from IRC server. + * @return {Object} A parsed message object. + */ +module.exports = function parseMessage(line) { + var message = {}; + var match; + + // Parse prefix + match = line.match(/^:([^ ]+) +/); + if (match) { + message.prefix = match[1]; + line = line.replace(/^:[^ ]+ +/, ''); + match = message.prefix.match(/^([_a-zA-Z0-9\~\[\]\\`^{}|-]*)(!([^@]+)@(.*))?$/); + if (match) { + message.nick = match[1]; + message.user = match[3]; + message.host = match[4]; + } + else { + message.server = message.prefix; + } + } + + // Parse command + match = line.match(/^([^ ]+) */); + message.command = match[1]; + message.rawCommand = match[1]; + message.commandType = 'normal'; + line = line.replace(/^[^ ]+ +/, ''); + + if (replyFor[message.rawCommand]) { + message.command = replyFor[message.rawCommand].name; + message.commandType = replyFor[message.rawCommand].type; + } + + message.args = []; + var middle, trailing; + + // Parse parameters + if (line.search(/^:|\s+:/) != -1) { + match = line.match(/(.*?)(?:^:|\s+:)(.*)/); + middle = match[1].trimRight(); + trailing = match[2]; + } + else { + middle = line; + } + + if (middle.length) + message.args = middle.split(/ +/); + + if (typeof (trailing) != 'undefined' && trailing.length) + message.args.push(trailing); + + return message; +} diff --git a/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js b/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js new file mode 100644 index 0000000000000..241adc33913bc --- /dev/null +++ b/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js @@ -0,0 +1,112 @@ +export default { + PASS: function (parsedMessage) { + this.log('Received PASS command, continue registering...') + + this.registerSteps.push('PASS') + }, + + SERVER: function (parsedMessage) { + this.log('Received SERVER command, waiting for first PING...') + + this.serverPrefix = parsedMessage.prefix + + this.registerSteps.push('SERVER') + }, + + PING: function (parsedMessage) { + if (!this.isRegistered && this.registerSteps.length === 2) { + this.log('Received first PING command, server is registered!') + + this.isRegistered = true + + this.emit('registered') + } + + this.write({ + prefix: this.config.server.name, + command: 'PONG', + parameters: [ this.config.server.name ] + }) + }, + + NICK: function (parsedMessage) { + let command + + // Check if the message comes from the server, + // which means it is a new user + if (parsedMessage.prefix === this.serverPrefix) { + command = { + identifier: 'userRegistered', + args: { + nick: parsedMessage.args[0], + username: parsedMessage.args[2].substring(1), + host: parsedMessage.args[3], + name: parsedMessage.args[6], + } + } + } else { // Otherwise, it is a nick change + command = { + identifier: 'nickChanged', + args: { + nick: parsedMessage.nick, + newNick: parsedMessage.args[0], + } + } + } + + return command + }, + + JOIN: function (parsedMessage) { + const command = { + identifier: 'joinedChannel', + args: { + roomName: parsedMessage.args[0].substring(1), + nick: parsedMessage.prefix + } + } + + return command + }, + + PART: function (parsedMessage) { + let command = { + identifier: 'leftChannel', + args: { + roomName: parsedMessage.args[0].substring(1), + nick: parsedMessage.prefix + } + } + + return command + }, + + PRIVMSG: function (parsedMessage) { + let command = { + identifier: 'sentMessage', + args: { + nick: parsedMessage.prefix, + message: parsedMessage.args[1] + } + } + + if (parsedMessage.args[0][0] === '#') { + command.args.roomName = parsedMessage.args[0].substring(1) + } else { + command.args.recipientNick = parsedMessage.args[0] + } + + return command + }, + + QUIT: function (parsedMessage) { + let command = { + identifier: 'disconnected', + args: { + nick: parsedMessage.prefix + } + } + + return command + } +} diff --git a/packages/rocketchat-irc/server/servers/index.js b/packages/rocketchat-irc/server/servers/index.js new file mode 100644 index 0000000000000..be54ec69c0cbd --- /dev/null +++ b/packages/rocketchat-irc/server/servers/index.js @@ -0,0 +1 @@ +export RFC2813 from './RFC2813' diff --git a/packages/rocketchat-irc/server/settings.js b/packages/rocketchat-irc/server/settings.js deleted file mode 100644 index 19aa6d8ca96eb..0000000000000 --- a/packages/rocketchat-irc/server/settings.js +++ /dev/null @@ -1,78 +0,0 @@ -Meteor.startup(function() { - RocketChat.settings.addGroup('IRC', function() { - - // Is this thing on? - this.add('IRC_Enabled', false, { - type: 'boolean', - i18nLabel: 'Enabled', - i18nDescription: 'IRC_Enabled', - alert: 'IRC Support is a work in progress. Use on a production system is not recommended at this time.' - }); - - // The IRC host server to talk to - this.add('IRC_Host', 'irc.freenode.net', { - type: 'string', - i18nLabel: 'Host', - i18nDescription: 'IRC_Hostname' - }); - - // The port to connect on the remote server - this.add('IRC_Port', 6667, { - type: 'int', - i18nLabel: 'Port', - i18nDescription: 'IRC_Port' - }); - - // Cache size of the messages we send the host IRC server - this.add('IRC_Message_Cache_Size', 200, { - type: 'int', - i18nLabel: 'Message Cache Size', - i18nDescription: 'IRC_Message_Cache_Size' - }); - - // Expandable box for modifying regular expressions for IRC interaction - this.section('Regular_Expressions', function() { - this.add('IRC_RegEx_successLogin', 'Welcome to the freenode Internet Relay Chat Network', { - type: 'string', - i18nLabel: 'Login Successful', - i18nDescription: 'IRC_Login_Success' - }); - this.add('IRC_RegEx_failedLogin', 'You have not registered', { - type: 'string', - i18nLabel: 'Login Failed', - i18nDescription: 'IRC_Login_Fail' - }); - this.add('IRC_RegEx_receiveMessage', '^:(\S+)!~\S+ PRIVMSG (\S+) :(.+)$', { - type: 'string', - i18nLabel: 'Private Message', - i18nDescription: 'IRC_Private_Message' - }); - this.add('IRC_RegEx_receiveMemberList', '^:\S+ \d+ \S+ = #(\S+) :(.*)$', { - type: 'string', - i18nLabel: 'Channel User List Start', - i18nDescription: 'IRC_Channel_Users' - }); - this.add('IRC_RegEx_endMemberList', '^.+#(\S+) :End of \/NAMES list.$', { - type: 'string', - i18nLabel: 'Channel User List End', - i18nDescription: 'IRC_Channel_Users_End' - }); - this.add('IRC_RegEx_addMemberToRoom', '^:(\S+)!~\S+ JOIN #(\S+)$', { - type: 'string', - i18nLabel: 'Join Channel', - i18nDescription: 'IRC_Channel_Join' - }); - this.add('IRC_RegEx_removeMemberFromRoom', '^:(\S+)!~\S+ PART #(\S+)$', { - type: 'string', - i18nLabel: 'Leave Channel', - i18nDescription: 'IRC_Channel_Leave' - }); - this.add('IRC_RegEx_quitMember', '^:(\S+)!~\S+ QUIT .*$', { - type: 'string', - i18nLabel: 'Quit IRC Session', - i18nDescription: 'IRC_Quit' - }); - }); - - }); -}); diff --git a/packages/rocketchat-livechat/.app/package-lock.json b/packages/rocketchat-livechat/.app/package-lock.json new file mode 100644 index 0000000000000..88f6eccd96f42 --- /dev/null +++ b/packages/rocketchat-livechat/.app/package-lock.json @@ -0,0 +1,874 @@ +{ + "name": "rocketchat-livechat", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.4" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "autolinker": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.6.2.tgz", + "integrity": "sha512-IKLGtYFb3jzGTtgCpb4bm//1sXmmmgmr0msKshhYoc7EsWmLCFvuyxLcEIfcZ5gbCgZGXrnXkOkcBblOFEnlog==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz", + "integrity": "sha512-pRyDdo73C8Nim3jwFJ7DWe3TZCgwDfWZ6nHS5LSdU77kWbj1frruvdndP02AOavtD4y8v6Fp2dolbHgp4SDrfg==", + "requires": { + "nan": "2.6.2", + "node-pre-gyp": "0.6.36" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jquery": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", + "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "moment": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", + "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", + "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" + }, + "node-pre-gyp": { + "version": "0.6.36", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", + "integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=", + "requires": { + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.5", + "request": "2.83.0", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "2.2.1", + "tar-pack": "3.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "rc": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.5.tgz", + "integrity": "sha1-J1zWh/bjs2zHVrqibf7oCnkDAf0=", + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.1" + } + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", + "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", + "requires": { + "debug": "2.6.9", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.4", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "toastr": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz", + "integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=", + "requires": { + "jquery": "3.3.1" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "underscore.string": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz", + "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=", + "requires": { + "sprintf-js": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } +} From a1766e9e8c6471c25b24699038ba0f9e909ef120 Mon Sep 17 00:00:00 2001 From: Hudell Date: Tue, 15 May 2018 10:25:51 -0300 Subject: [PATCH 18/26] Fixing lint errors --- packages/rocketchat-irc/package.js | 2 +- .../rocketchat-irc/server/irc-bridge/index.js | 96 +- .../server/irc-bridge/localHandlers/index.js | 14 +- .../irc-bridge/localHandlers/onCreateRoom.js | 22 +- .../irc-bridge/localHandlers/onJoinRoom.js | 2 +- .../irc-bridge/localHandlers/onLeaveRoom.js | 2 +- .../irc-bridge/localHandlers/onLogin.js | 36 +- .../irc-bridge/localHandlers/onLogout.js | 6 +- .../irc-bridge/localHandlers/onSaveMessage.js | 22 +- .../irc-bridge/peerHandlers/disconnected.js | 18 +- .../server/irc-bridge/peerHandlers/index.js | 14 +- .../irc-bridge/peerHandlers/joinedChannel.js | 30 +- .../irc-bridge/peerHandlers/leftChannel.js | 24 +- .../irc-bridge/peerHandlers/nickChanged.js | 28 +- .../irc-bridge/peerHandlers/sentMessage.js | 114 +- .../irc-bridge/peerHandlers/userRegistered.js | 72 +- .../rocketchat-irc/server/irc-settings.js | 24 +- packages/rocketchat-irc/server/irc.js | 40 +- .../server/servers/RFC2813/codes.js | 1024 ++++++++--------- .../server/servers/RFC2813/index.js | 311 ++--- .../servers/RFC2813/localCommandHandlers.js | 123 +- .../server/servers/RFC2813/parseMessage.js | 91 +- .../servers/RFC2813/peerCommandHandlers.js | 222 ++-- .../rocketchat-irc/server/servers/index.js | 4 +- 24 files changed, 1176 insertions(+), 1165 deletions(-) diff --git a/packages/rocketchat-irc/package.js b/packages/rocketchat-irc/package.js index d6429869544db..0b9be6f5d5eb4 100644 --- a/packages/rocketchat-irc/package.js +++ b/packages/rocketchat-irc/package.js @@ -5,7 +5,7 @@ Package.describe({ git: '' }); -Package.onUse(function (api) { +Package.onUse(function(api) { api.use([ 'ecmascript', 'underscore', diff --git a/packages/rocketchat-irc/server/irc-bridge/index.js b/packages/rocketchat-irc/server/irc-bridge/index.js index 1cb2b072afaf4..69c8df9453786 100644 --- a/packages/rocketchat-irc/server/irc-bridge/index.js +++ b/packages/rocketchat-irc/server/irc-bridge/index.js @@ -1,50 +1,48 @@ -import _ from 'underscore' -import Queue from 'queue-fifo' - -import * as servers from '../servers' -import * as peerCommandHandlers from './peerHandlers' -import * as localCommandHandlers from './localHandlers' +import Queue from 'queue-fifo'; +import * as servers from '../servers'; +import * as peerCommandHandlers from './peerHandlers'; +import * as localCommandHandlers from './localHandlers'; class Bridge { constructor(config) { // General - this.config = config + this.config = config; // Workaround for Rocket.Chat callbacks being called multiple times - this.loggedInUsers = [] + this.loggedInUsers = []; // Server - const Server = servers[this.config.server.protocol] + const Server = servers[this.config.server.protocol]; - this.server = new Server(this.config) + this.server = new Server(this.config); - this.setupPeerHandlers() - this.setupLocalHandlers() + this.setupPeerHandlers(); + this.setupLocalHandlers(); // Command queue - this.queue = new Queue() - this.queueTimeout = 5 + this.queue = new Queue(); + this.queueTimeout = 5; } init() { - this.server.register() + this.server.register(); this.server.on('registered', () => { - this.logQueue('Starting...') + this.logQueue('Starting...'); - this.runQueue() - }) + this.runQueue(); + }); } - /** - * Log helper - */ + /** + * Log helper + */ log(message) { - console.log(`[irc][bridge] ${message}`) + console.log(`[irc][bridge] ${ message }`); } logQueue(message) { - console.log(`[irc][bridge][queue] ${message}`) + console.log(`[irc][bridge][queue] ${ message }`); } /** @@ -55,36 +53,40 @@ class Bridge { * */ onMessageReceived(from, command, ...parameters) { - this.queue.enqueue({ from, command, parameters }) + this.queue.enqueue({ from, command, parameters }); } async runQueue() { // If it is empty, skip and keep the queue going - if(this.queue.isEmpty()) { - return setTimeout(this.runQueue.bind(this), this.queueTimeout) + if (this.queue.isEmpty()) { + return setTimeout(this.runQueue.bind(this), this.queueTimeout); } // Get the command - const item = this.queue.dequeue() + const item = this.queue.dequeue(); - this.logQueue(`Processing "${item.command}" command from "${item.from}"`) + this.logQueue(`Processing "${ item.command }" command from "${ item.from }"`); // Handle the command accordingly - switch(item.from) { + switch (item.from) { case 'local': - if (!localCommandHandlers[item.command]) throw new Error(`Could not find handler for local:${item.command}`) + if (!localCommandHandlers[item.command]) { + throw new Error(`Could not find handler for local:${ item.command }`); + } - await localCommandHandlers[item.command].apply(this, item.parameters) - break + await localCommandHandlers[item.command].apply(this, item.parameters); + break; case 'peer': - if (!peerCommandHandlers[item.command]) throw new Error(`Could not find handler for peer:${item.command}`) + if (!peerCommandHandlers[item.command]) { + throw new Error(`Could not find handler for peer:${ item.command }`); + } - await peerCommandHandlers[item.command].apply(this, item.parameters) - break + await peerCommandHandlers[item.command].apply(this, item.parameters); + break; } // Keep the queue going - setTimeout(this.runQueue.bind(this), this.queueTimeout) + setTimeout(this.runQueue.bind(this), this.queueTimeout); } /** @@ -96,8 +98,8 @@ class Bridge { */ setupPeerHandlers() { this.server.on('peerCommand', (cmd) => { - this.onMessageReceived('peer', cmd.identifier, cmd.args) - }) + this.onMessageReceived('peer', cmd.identifier, cmd.args); + }); } /** @@ -109,22 +111,22 @@ class Bridge { */ setupLocalHandlers() { // Auth - RocketChat.callbacks.add('afterValidateLogin', this.onMessageReceived.bind(this, 'local', 'onLogin'), RocketChat.callbacks.priority.LOW, 'irc-on-login') + RocketChat.callbacks.add('afterValidateLogin', this.onMessageReceived.bind(this, 'local', 'onLogin'), RocketChat.callbacks.priority.LOW, 'irc-on-login'); // Joining rooms or channels - RocketChat.callbacks.add('afterCreateChannel', this.onMessageReceived.bind(this, 'local', 'onCreateRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-create-channel') - RocketChat.callbacks.add('afterCreateRoom', this.onMessageReceived.bind(this, 'local', 'onCreateRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-create-room') - RocketChat.callbacks.add('afterJoinRoom', this.onMessageReceived.bind(this, 'local', 'onJoinRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-join-room') + RocketChat.callbacks.add('afterCreateChannel', this.onMessageReceived.bind(this, 'local', 'onCreateRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-create-channel'); + RocketChat.callbacks.add('afterCreateRoom', this.onMessageReceived.bind(this, 'local', 'onCreateRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-create-room'); + RocketChat.callbacks.add('afterJoinRoom', this.onMessageReceived.bind(this, 'local', 'onJoinRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-join-room'); // Leaving rooms or channels - RocketChat.callbacks.add('afterLeaveRoom', this.onMessageReceived.bind(this, 'local', 'onLeaveRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-leave-room') + RocketChat.callbacks.add('afterLeaveRoom', this.onMessageReceived.bind(this, 'local', 'onLeaveRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-leave-room'); // Chatting - RocketChat.callbacks.add('afterSaveMessage', this.onMessageReceived.bind(this, 'local', 'onSaveMessage'), RocketChat.callbacks.priority.LOW, 'irc-on-save-message') + RocketChat.callbacks.add('afterSaveMessage', this.onMessageReceived.bind(this, 'local', 'onSaveMessage'), RocketChat.callbacks.priority.LOW, 'irc-on-save-message'); // Leaving - RocketChat.callbacks.add('afterLogoutCleanUp', this.onMessageReceived.bind(this, 'local', 'onLogout'), RocketChat.callbacks.priority.LOW, 'irc-on-logout') + RocketChat.callbacks.add('afterLogoutCleanUp', this.onMessageReceived.bind(this, 'local', 'onLogout'), RocketChat.callbacks.priority.LOW, 'irc-on-logout'); } sendCommand(command, parameters) { - this.server.emit('onReceiveFromLocal', command, parameters) + this.server.emit('onReceiveFromLocal', command, parameters); } } -export default Bridge +export default Bridge; diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js index 6d706b813486c..7ca62f5544919 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js @@ -1,6 +1,8 @@ -export onCreateRoom from './onCreateRoom' -export onJoinRoom from './onJoinRoom' -export onLeaveRoom from './onLeaveRoom' -export onLogin from './onLogin' -export onLogout from './onLogout' -export onSaveMessage from './onSaveMessage' +import onCreateRoom from './onCreateRoom'; +import onJoinRoom from './onJoinRoom'; +import onLeaveRoom from './onLeaveRoom'; +import onLogin from './onLogin'; +import onLogout from './onLogout'; +import onSaveMessage from './onSaveMessage'; + +export { onCreateRoom, onJoinRoom, onLeaveRoom, onLogin, onLogout, onSaveMessage }; diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateRoom.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateRoom.js index 88e652f912e87..7ca1dc2614ded 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateRoom.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateRoom.js @@ -1,15 +1,15 @@ export default function handleOnCreateRoom(user, room) { - if (!room.usernames) { - return this.log(`Room ${room.name} does not have a valid list of usernames`) - } + if (!room.usernames) { + return this.log(`Room ${ room.name } does not have a valid list of usernames`); + } - for (const username of room.usernames) { - const user = RocketChat.models.Users.findOne({ username }) + for (const username of room.usernames) { + const user = RocketChat.models.Users.findOne({ username }); - if (user.profile.irc.fromIRC) { - this.sendCommand('joinChannel', { room, user }) - } else { - this.sendCommand('joinedChannel', { room, user }) - } - } + if (user.profile.irc.fromIRC) { + this.sendCommand('joinChannel', { room, user }); + } else { + this.sendCommand('joinedChannel', { room, user }); + } + } } diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onJoinRoom.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onJoinRoom.js index 0a4a14405f50a..34da322701e81 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onJoinRoom.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onJoinRoom.js @@ -1,3 +1,3 @@ export default function handleOnJoinRoom(user, room) { - this.sendCommand('joinedChannel', { room, user }) + this.sendCommand('joinedChannel', { room, user }); } diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLeaveRoom.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLeaveRoom.js index ddf90f2462b57..32775f42dd978 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLeaveRoom.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLeaveRoom.js @@ -1,3 +1,3 @@ export default function handleOnLeaveRoom(user, room) { - this.sendCommand('leftChannel', { room, user }) + this.sendCommand('leftChannel', { room, user }); } diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js index bfec2b8e15d95..8680e9f509ca0 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js @@ -1,26 +1,26 @@ export default function handleOnLogin(login) { - if (login.user === null || this.loggedInUsers.indexOf(login.user._id) !== -1) { - return this.log('Invalid or duplicate handleOnLogin call') - } + if (login.user === null || this.loggedInUsers.indexOf(login.user._id) !== -1) { + return this.log('Invalid or duplicate handleOnLogin call'); + } - this.loggedInUsers.push(login.user._id) + this.loggedInUsers.push(login.user._id); - Meteor.users.update({ _id: login.user._id }, { - $set: { - 'profile.irc.fromIRC': false, - 'profile.irc.username': `${login.user.username}-rkt`, - 'profile.irc.nick': `${login.user.username}-rkt`, - 'profile.irc.hostname': 'rocket.chat' - } - }) + Meteor.users.update({ _id: login.user._id }, { + $set: { + 'profile.irc.fromIRC': false, + 'profile.irc.username': `${ login.user.username }-rkt`, + 'profile.irc.nick': `${ login.user.username }-rkt`, + 'profile.irc.hostname': 'rocket.chat' + } + }); - const user = RocketChat.models.Users.findOne({ - _id: login.user._id - }) + const user = RocketChat.models.Users.findOne({ + _id: login.user._id + }); - this.sendCommand('registerUser', user) + this.sendCommand('registerUser', user); - const rooms = RocketChat.models.Rooms.findWithUsername(user.username).fetch() + const rooms = RocketChat.models.Rooms.findWithUsername(user.username).fetch(); - rooms.forEach(room => this.sendCommand('joinedChannel', { room, user })) + rooms.forEach(room => this.sendCommand('joinedChannel', { room, user })); } diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogout.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogout.js index c6a912774d956..a2669285ae9ee 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogout.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogout.js @@ -1,5 +1,7 @@ +import _ from 'underscore'; + export default function handleOnLogout(user) { - this.loggedInUsers = _.without(this.loggedInUsers, user._id) + this.loggedInUsers = _.without(this.loggedInUsers, user._id); - this.sendCommand('disconnected', { user }) + this.sendCommand('disconnected', { user }); } diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js index f6e09ed441dd5..6c937fd057910 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js @@ -1,16 +1,18 @@ +import _ from 'underscore'; + export default function handleOnSaveMessage(message, to) { - let toIdentification = '' + let toIdentification = ''; - // Direct message - if (to.t === 'd') { - const recipientUser = RocketChat.models.Users.findOne({ username: _.without(to.usernames, to.username)[0] }) + // Direct message + if (to.t === 'd') { + const recipientUser = RocketChat.models.Users.findOne({ username: _.without(to.usernames, to.username)[0] }); - toIdentification = recipientUser.profile.irc.nick - } else { - toIdentification = `#${to.name}` - } + toIdentification = recipientUser.profile.irc.nick; + } else { + toIdentification = `#${ to.name }`; + } - const user = RocketChat.models.Users.findOne({ _id: message.u._id }) + const user = RocketChat.models.Users.findOne({ _id: message.u._id }); - this.sendCommand('sentMessage', { to: toIdentification, user, message: message.msg }) + this.sendCommand('sentMessage', { to: toIdentification, user, message: message.msg }); } diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/disconnected.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/disconnected.js index 31a5ed5653db5..86c82e9263424 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/disconnected.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/disconnected.js @@ -1,13 +1,13 @@ export default function handleQUIT(args) { - let user = RocketChat.models.Users.findOne({ - 'profile.irc.nick': args.nick - }) + const user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }); - Meteor.users.update({ _id: user._id }, { - $set: { - status: 'offline' - } - }) + Meteor.users.update({ _id: user._id }, { + $set: { + status: 'offline' + } + }); - RocketChat.models.Rooms.removeUsernameFromAll(user.username) + RocketChat.models.Rooms.removeUsernameFromAll(user.username); } diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/index.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/index.js index 2084cd70e5522..00397f667f68c 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/index.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/index.js @@ -1,6 +1,8 @@ -export disconnected from './disconnected' -export joinedChannel from './joinedChannel' -export leftChannel from './leftChannel' -export nickChanged from './nickChanged' -export sentMessage from './sentMessage' -export userRegistered from './userRegistered' +import disconnected from './disconnected'; +import joinedChannel from './joinedChannel'; +import leftChannel from './leftChannel'; +import nickChanged from './nickChanged'; +import sentMessage from './sentMessage'; +import userRegistered from './userRegistered'; + +export { disconnected, joinedChannel, leftChannel, nickChanged, sentMessage, userRegistered }; diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js index 7a4f4dd6c4720..1dfae5873f294 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js @@ -1,22 +1,22 @@ export default function handleJoinedChannel(args) { - let user = RocketChat.models.Users.findOne({ - 'profile.irc.nick': args.nick - }) + const user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }); - if (!user) { - throw new Error(`Could not find a user with nick ${args.nick}`) - } + if (!user) { + throw new Error(`Could not find a user with nick ${ args.nick }`); + } - let room = RocketChat.models.Rooms.findOneByName(args.roomName) + let room = RocketChat.models.Rooms.findOneByName(args.roomName); - if (!room) { - const createdRoom = RocketChat.createRoom('c', args.roomName, user.username, [ /* usernames of the participants here */]) - room = RocketChat.models.Rooms.findOne({ _id: createdRoom.rid }) + if (!room) { + const createdRoom = RocketChat.createRoom('c', args.roomName, user.username, [ /* usernames of the participants here */]); + room = RocketChat.models.Rooms.findOne({ _id: createdRoom.rid }); - this.log(`${user.username} created room ${args.roomName}`) - } else { - RocketChat.addUserToRoom(room._id, user) + this.log(`${ user.username } created room ${ args.roomName }`); + } else { + RocketChat.addUserToRoom(room._id, user); - this.log(`${user.username} joined room ${room.name}`) - } + this.log(`${ user.username } joined room ${ room.name }`); + } } diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/leftChannel.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/leftChannel.js index 09f84bdcba9ba..c8065fe3b1101 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/leftChannel.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/leftChannel.js @@ -1,18 +1,18 @@ export default function handleLeftChannel(args) { - let user = RocketChat.models.Users.findOne({ - 'profile.irc.nick': args.nick - }) + const user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }); - if (!user) { - throw new Error(`Could not find a user with nick ${args.nick}`) - } + if (!user) { + throw new Error(`Could not find a user with nick ${ args.nick }`); + } - let room = RocketChat.models.Rooms.findOneByName(args.roomName) + const room = RocketChat.models.Rooms.findOneByName(args.roomName); - if (!room) { - throw new Error(`Could not find a room with name ${args.roomName}`) - } + if (!room) { + throw new Error(`Could not find a room with name ${ args.roomName }`); + } - this.log(`${user.username} left room ${room.name}`) - RocketChat.removeUserFromRoom(room._id, user) + this.log(`${ user.username } left room ${ room.name }`); + RocketChat.removeUserFromRoom(room._id, user); } diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/nickChanged.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/nickChanged.js index 4c1e8eb76379a..9b09f369ce929 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/nickChanged.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/nickChanged.js @@ -1,19 +1,19 @@ export default function handleNickChanged(args) { - let user = RocketChat.models.Users.findOne({ - 'profile.irc.nick': args.nick - }) + const user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }); - if (!user) { - throw new Error(`Could not find an user with nick ${args.nick}`) - } + if (!user) { + throw new Error(`Could not find an user with nick ${ args.nick }`); + } - this.log(`${user.username} changed nick: ${args.nick} -> ${args.newNick}`) + this.log(`${ user.username } changed nick: ${ args.nick } -> ${ args.newNick }`); - // Update on the database - RocketChat.models.Users.update({ _id: user._id }, { - $set: { - name: args.newNick, - 'profile.irc.nick': args.newNick - } - }) + // Update on the database + RocketChat.models.Users.update({ _id: user._id }, { + $set: { + name: args.newNick, + 'profile.irc.nick': args.newNick + } + }); } diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js index 288e73a3d9a7f..3bad240600681 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js @@ -1,32 +1,3 @@ -export default function handleSentMessage(args) { - let user = RocketChat.models.Users.findOne({ - 'profile.irc.nick': args.nick - }) - - if (!user) { - throw new Error(`Could not find a user with nick ${args.nick}`) - } - - let room - - if (args.roomName) { - room = RocketChat.models.Rooms.findOneByName(args.roomName) - } else { - const recipientUser = RocketChat.models.Users.findOne({ - 'profile.irc.nick': args.recipientNick - }) - - room = getDirectRoom(user, recipientUser) - } - - const message = { - msg: args.message, - ts: new Date() - } - - RocketChat.sendMessage(user, message, room) -} - /* * * Get direct chat room helper @@ -34,35 +5,64 @@ export default function handleSentMessage(args) { * */ const getDirectRoom = (source, target) => { - const rid = [ source._id, target._id ].sort().join('') + const rid = [ source._id, target._id ].sort().join(''); + + RocketChat.models.Rooms.upsert({ _id: rid }, { + $set: { + usernames: [source.username, target.username] + }, + $setOnInsert: { + t: 'd', + msgs: 0, + ts: new Date() + } + }); + + RocketChat.models.Subscriptions.upsert({rid, 'u._id': target._id}, { + $setOnInsert: { + name: source.username, + t: 'd', + open: false, + alert: false, + unread: 0, + u: { + _id: target._id, + username: target.username + } + } + }); + + return { + _id: rid, + t: 'd' + }; +}; + +export default function handleSentMessage(args) { + const user = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.nick + }); + + if (!user) { + throw new Error(`Could not find a user with nick ${ args.nick }`); + } + + let room; + + if (args.roomName) { + room = RocketChat.models.Rooms.findOneByName(args.roomName); + } else { + const recipientUser = RocketChat.models.Users.findOne({ + 'profile.irc.nick': args.recipientNick + }); - RocketChat.models.Rooms.upsert({ _id: rid }, { - $set: { - usernames: [source.username, target.username] - }, - $setOnInsert: { - t: 'd', - msgs: 0, - ts: new Date() - } - }) + room = getDirectRoom(user, recipientUser); + } - RocketChat.models.Subscriptions.upsert({rid, 'u._id': target._id}, { - $setOnInsert: { - name: source.username, - t: 'd', - open: false, - alert: false, - unread: 0, - u: { - _id: target._id, - username: target.username - } - } - }) + const message = { + msg: args.message, + ts: new Date() + }; - return { - _id: rid, - t: 'd' - } + RocketChat.sendMessage(user, message, room); } diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/userRegistered.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/userRegistered.js index d8b7ee6e1a32d..d87d8764a10b3 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/userRegistered.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/userRegistered.js @@ -1,42 +1,42 @@ export default async function handleUserRegistered(args) { - // Check if there is an user with the given username - let user = RocketChat.models.Users.findOne({ - 'profile.irc.username': args.username - }) + // Check if there is an user with the given username + let user = RocketChat.models.Users.findOne({ + 'profile.irc.username': args.username + }); - // If there is no user, create one... - if (!user) { - this.log(`Registering ${args.username} with nick: ${args.nick}`) + // If there is no user, create one... + if (!user) { + this.log(`Registering ${ args.username } with nick: ${ args.nick }`); - const userToInsert = { - name: args.nick, - username: `${args.username}-irc`, - status: 'online', - utcOffset: 0, - active: true, - type: 'user', - profile: { - irc: { - fromIRC: true, - nick: args.nick, - username: args.username, - hostname: args.hostname - } - } - } + const userToInsert = { + name: args.nick, + username: `${ args.username }-irc`, + status: 'online', + utcOffset: 0, + active: true, + type: 'user', + profile: { + irc: { + fromIRC: true, + nick: args.nick, + username: args.username, + hostname: args.hostname + } + } + }; - user = RocketChat.models.Users.create(userToInsert) - } else { - // ...otherwise, log the user in and update the information - this.log(`Logging in ${args.username} with nick: ${args.nick}`) + user = RocketChat.models.Users.create(userToInsert); + } else { + // ...otherwise, log the user in and update the information + this.log(`Logging in ${ args.username } with nick: ${ args.nick }`); - Meteor.users.update({ _id: user._id }, { - $set: { - status: 'online', - 'profile.irc.nick': args.nick, - 'profile.irc.username': args.username, - 'profile.irc.hostname': args.hostname, - } - }) - } + Meteor.users.update({ _id: user._id }, { + $set: { + status: 'online', + 'profile.irc.nick': args.nick, + 'profile.irc.username': args.username, + 'profile.irc.hostname': args.hostname + } + }); + } } diff --git a/packages/rocketchat-irc/server/irc-settings.js b/packages/rocketchat-irc/server/irc-settings.js index 740ee90f55c55..b452718345bb4 100644 --- a/packages/rocketchat-irc/server/irc-settings.js +++ b/packages/rocketchat-irc/server/irc-settings.js @@ -1,10 +1,10 @@ -Meteor.startup(function () { - RocketChat.settings.addGroup('IRC', function () { +Meteor.startup(function() { + RocketChat.settings.addGroup('IRC', function() { this.add('IRC_Enabled', false, { type: 'boolean', i18nLabel: 'Enabled', i18nDescription: 'IRC_Enabled' - }) + }); this.add('IRC_Protocol', 'RFC2813', { type: 'select', @@ -16,42 +16,42 @@ Meteor.startup(function () { i18nLabel: 'RFC2813' } ] - }) + }); this.add('IRC_Host', 'localhost', { type: 'string', i18nLabel: 'Host', i18nDescription: 'IRC_Host' - }) + }); this.add('IRC_Port', 6667, { type: 'int', i18nLabel: 'Port', i18nDescription: 'IRC_Port' - }) + }); this.add('IRC_Name', 'irc.rocket.chat', { type: 'string', i18nLabel: 'Name', i18nDescription: 'IRC_Name' - }) + }); this.add('IRC_Description', 'Rocket.Chat IRC Bridge', { type: 'string', i18nLabel: 'Description', i18nDescription: 'IRC_Description' - }) + }); this.add('IRC_Local_Password', 'password', { type: 'string', i18nLabel: 'Local_Password', i18nDescription: 'IRC_Local_Password' - }) + }); this.add('IRC_Peer_Password', 'password', { type: 'string', i18nLabel: 'Peer_Password', i18nDescription: 'IRC_Peer_Password' - }) - }) -}) + }); + }); +}); diff --git a/packages/rocketchat-irc/server/irc.js b/packages/rocketchat-irc/server/irc.js index e6eea32a3205d..ffdb0bcdc9a29 100644 --- a/packages/rocketchat-irc/server/irc.js +++ b/packages/rocketchat-irc/server/irc.js @@ -1,26 +1,24 @@ -import _ from 'underscore'; - import Bridge from './irc-bridge'; if (!!RocketChat.settings.get('IRC_Enabled') === true) { - // Normalize the config values - const config = { - server: { - protocol: RocketChat.settings.get('IRC_Protocol'), - host: RocketChat.settings.get('IRC_Host'), - port: RocketChat.settings.get('IRC_Port'), - name: RocketChat.settings.get('IRC_Name'), - description: RocketChat.settings.get('IRC_Description') - }, - passwords: { - local: RocketChat.settings.get('IRC_Local_Password'), - peer: RocketChat.settings.get('IRC_Peer_Password') - } - }; + // Normalize the config values + const config = { + server: { + protocol: RocketChat.settings.get('IRC_Protocol'), + host: RocketChat.settings.get('IRC_Host'), + port: RocketChat.settings.get('IRC_Port'), + name: RocketChat.settings.get('IRC_Name'), + description: RocketChat.settings.get('IRC_Description') + }, + passwords: { + local: RocketChat.settings.get('IRC_Local_Password'), + peer: RocketChat.settings.get('IRC_Peer_Password') + } + }; - const bridge = new Bridge(config); + const bridge = new Bridge(config); - Meteor.startup(() => { - bridge.init(); - }); -}; + Meteor.startup(() => { + bridge.init(); + }); +} diff --git a/packages/rocketchat-irc/server/servers/RFC2813/codes.js b/packages/rocketchat-irc/server/servers/RFC2813/codes.js index 717ea674047ce..3071edfeee5d0 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/codes.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/codes.js @@ -4,516 +4,516 @@ */ module.exports = { - '001': { - name: 'rpl_welcome', - type: 'reply' - }, - '002': { - name: 'rpl_yourhost', - type: 'reply' - }, - '003': { - name: 'rpl_created', - type: 'reply' - }, - '004': { - name: 'rpl_myinfo', - type: 'reply' - }, - '005': { - name: 'rpl_isupport', - type: 'reply' - }, - 200: { - name: 'rpl_tracelink', - type: 'reply' - }, - 201: { - name: 'rpl_traceconnecting', - type: 'reply' - }, - 202: { - name: 'rpl_tracehandshake', - type: 'reply' - }, - 203: { - name: 'rpl_traceunknown', - type: 'reply' - }, - 204: { - name: 'rpl_traceoperator', - type: 'reply' - }, - 205: { - name: 'rpl_traceuser', - type: 'reply' - }, - 206: { - name: 'rpl_traceserver', - type: 'reply' - }, - 208: { - name: 'rpl_tracenewtype', - type: 'reply' - }, - 211: { - name: 'rpl_statslinkinfo', - type: 'reply' - }, - 212: { - name: 'rpl_statscommands', - type: 'reply' - }, - 213: { - name: 'rpl_statscline', - type: 'reply' - }, - 214: { - name: 'rpl_statsnline', - type: 'reply' - }, - 215: { - name: 'rpl_statsiline', - type: 'reply' - }, - 216: { - name: 'rpl_statskline', - type: 'reply' - }, - 218: { - name: 'rpl_statsyline', - type: 'reply' - }, - 219: { - name: 'rpl_endofstats', - type: 'reply' - }, - 221: { - name: 'rpl_umodeis', - type: 'reply' - }, - 241: { - name: 'rpl_statslline', - type: 'reply' - }, - 242: { - name: 'rpl_statsuptime', - type: 'reply' - }, - 243: { - name: 'rpl_statsoline', - type: 'reply' - }, - 244: { - name: 'rpl_statshline', - type: 'reply' - }, - 250: { - name: 'rpl_statsconn', - type: 'reply' - }, - 251: { - name: 'rpl_luserclient', - type: 'reply' - }, - 252: { - name: 'rpl_luserop', - type: 'reply' - }, - 253: { - name: 'rpl_luserunknown', - type: 'reply' - }, - 254: { - name: 'rpl_luserchannels', - type: 'reply' - }, - 255: { - name: 'rpl_luserme', - type: 'reply' - }, - 256: { - name: 'rpl_adminme', - type: 'reply' - }, - 257: { - name: 'rpl_adminloc1', - type: 'reply' - }, - 258: { - name: 'rpl_adminloc2', - type: 'reply' - }, - 259: { - name: 'rpl_adminemail', - type: 'reply' - }, - 261: { - name: 'rpl_tracelog', - type: 'reply' - }, - 265: { - name: 'rpl_localusers', - type: 'reply' - }, - 266: { - name: 'rpl_globalusers', - type: 'reply' - }, - 300: { - name: 'rpl_none', - type: 'reply' - }, - 301: { - name: 'rpl_away', - type: 'reply' - }, - 302: { - name: 'rpl_userhost', - type: 'reply' - }, - 303: { - name: 'rpl_ison', - type: 'reply' - }, - 305: { - name: 'rpl_unaway', - type: 'reply' - }, - 306: { - name: 'rpl_nowaway', - type: 'reply' - }, - 311: { - name: 'rpl_whoisuser', - type: 'reply' - }, - 312: { - name: 'rpl_whoisserver', - type: 'reply' - }, - 313: { - name: 'rpl_whoisoperator', - type: 'reply' - }, - 314: { - name: 'rpl_whowasuser', - type: 'reply' - }, - 315: { - name: 'rpl_endofwho', - type: 'reply' - }, - 317: { - name: 'rpl_whoisidle', - type: 'reply' - }, - 318: { - name: 'rpl_endofwhois', - type: 'reply' - }, - 319: { - name: 'rpl_whoischannels', - type: 'reply' - }, - 321: { - name: 'rpl_liststart', - type: 'reply' - }, - 322: { - name: 'rpl_list', - type: 'reply' - }, - 323: { - name: 'rpl_listend', - type: 'reply' - }, - 324: { - name: 'rpl_channelmodeis', - type: 'reply' - }, - 329: { - name: 'rpl_creationtime', - type: 'reply' - }, - 331: { - name: 'rpl_notopic', - type: 'reply' - }, - 332: { - name: 'rpl_topic', - type: 'reply' - }, - 333: { - name: 'rpl_topicwhotime', - type: 'reply' - }, - 341: { - name: 'rpl_inviting', - type: 'reply' - }, - 342: { - name: 'rpl_summoning', - type: 'reply' - }, - 351: { - name: 'rpl_version', - type: 'reply' - }, - 352: { - name: 'rpl_whoreply', - type: 'reply' - }, - 353: { - name: 'rpl_namreply', - type: 'reply' - }, - 364: { - name: 'rpl_links', - type: 'reply' - }, - 365: { - name: 'rpl_endoflinks', - type: 'reply' - }, - 366: { - name: 'rpl_endofnames', - type: 'reply' - }, - 367: { - name: 'rpl_banlist', - type: 'reply' - }, - 368: { - name: 'rpl_endofbanlist', - type: 'reply' - }, - 369: { - name: 'rpl_endofwhowas', - type: 'reply' - }, - 371: { - name: 'rpl_info', - type: 'reply' - }, - 372: { - name: 'rpl_motd', - type: 'reply' - }, - 374: { - name: 'rpl_endofinfo', - type: 'reply' - }, - 375: { - name: 'rpl_motdstart', - type: 'reply' - }, - 376: { - name: 'rpl_endofmotd', - type: 'reply' - }, - 381: { - name: 'rpl_youreoper', - type: 'reply' - }, - 382: { - name: 'rpl_rehashing', - type: 'reply' - }, - 391: { - name: 'rpl_time', - type: 'reply' - }, - 392: { - name: 'rpl_usersstart', - type: 'reply' - }, - 393: { - name: 'rpl_users', - type: 'reply' - }, - 394: { - name: 'rpl_endofusers', - type: 'reply' - }, - 395: { - name: 'rpl_nousers', - type: 'reply' - }, - 401: { - name: 'err_nosuchnick', - type: 'error' - }, - 402: { - name: 'err_nosuchserver', - type: 'error' - }, - 403: { - name: 'err_nosuchchannel', - type: 'error' - }, - 404: { - name: 'err_cannotsendtochan', - type: 'error' - }, - 405: { - name: 'err_toomanychannels', - type: 'error' - }, - 406: { - name: 'err_wasnosuchnick', - type: 'error' - }, - 407: { - name: 'err_toomanytargets', - type: 'error' - }, - 409: { - name: 'err_noorigin', - type: 'error' - }, - 411: { - name: 'err_norecipient', - type: 'error' - }, - 412: { - name: 'err_notexttosend', - type: 'error' - }, - 413: { - name: 'err_notoplevel', - type: 'error' - }, - 414: { - name: 'err_wildtoplevel', - type: 'error' - }, - 421: { - name: 'err_unknowncommand', - type: 'error' - }, - 422: { - name: 'err_nomotd', - type: 'error' - }, - 423: { - name: 'err_noadmininfo', - type: 'error' - }, - 424: { - name: 'err_fileerror', - type: 'error' - }, - 431: { - name: 'err_nonicknamegiven', - type: 'error' - }, - 432: { - name: 'err_erroneusnickname', - type: 'error' - }, - 433: { - name: 'err_nicknameinuse', - type: 'error' - }, - 436: { - name: 'err_nickcollision', - type: 'error' - }, - 441: { - name: 'err_usernotinchannel', - type: 'error' - }, - 442: { - name: 'err_notonchannel', - type: 'error' - }, - 443: { - name: 'err_useronchannel', - type: 'error' - }, - 444: { - name: 'err_nologin', - type: 'error' - }, - 445: { - name: 'err_summondisabled', - type: 'error' - }, - 446: { - name: 'err_usersdisabled', - type: 'error' - }, - 451: { - name: 'err_notregistered', - type: 'error' - }, - 461: { - name: 'err_needmoreparams', - type: 'error' - }, - 462: { - name: 'err_alreadyregistred', - type: 'error' - }, - 463: { - name: 'err_nopermforhost', - type: 'error' - }, - 464: { - name: 'err_passwdmismatch', - type: 'error' - }, - 465: { - name: 'err_yourebannedcreep', - type: 'error' - }, - 467: { - name: 'err_keyset', - type: 'error' - }, - 471: { - name: 'err_channelisfull', - type: 'error' - }, - 472: { - name: 'err_unknownmode', - type: 'error' - }, - 473: { - name: 'err_inviteonlychan', - type: 'error' - }, - 474: { - name: 'err_bannedfromchan', - type: 'error' - }, - 475: { - name: 'err_badchannelkey', - type: 'error' - }, - 481: { - name: 'err_noprivileges', - type: 'error' - }, - 482: { - name: 'err_chanoprivsneeded', - type: 'error' - }, - 483: { - name: 'err_cantkillserver', - type: 'error' - }, - 491: { - name: 'err_nooperhost', - type: 'error' - }, - 501: { - name: 'err_umodeunknownflag', - type: 'error' - }, - 502: { - name: 'err_usersdontmatch', - type: 'error' - } + '001': { + name: 'rpl_welcome', + type: 'reply' + }, + '002': { + name: 'rpl_yourhost', + type: 'reply' + }, + '003': { + name: 'rpl_created', + type: 'reply' + }, + '004': { + name: 'rpl_myinfo', + type: 'reply' + }, + '005': { + name: 'rpl_isupport', + type: 'reply' + }, + 200: { + name: 'rpl_tracelink', + type: 'reply' + }, + 201: { + name: 'rpl_traceconnecting', + type: 'reply' + }, + 202: { + name: 'rpl_tracehandshake', + type: 'reply' + }, + 203: { + name: 'rpl_traceunknown', + type: 'reply' + }, + 204: { + name: 'rpl_traceoperator', + type: 'reply' + }, + 205: { + name: 'rpl_traceuser', + type: 'reply' + }, + 206: { + name: 'rpl_traceserver', + type: 'reply' + }, + 208: { + name: 'rpl_tracenewtype', + type: 'reply' + }, + 211: { + name: 'rpl_statslinkinfo', + type: 'reply' + }, + 212: { + name: 'rpl_statscommands', + type: 'reply' + }, + 213: { + name: 'rpl_statscline', + type: 'reply' + }, + 214: { + name: 'rpl_statsnline', + type: 'reply' + }, + 215: { + name: 'rpl_statsiline', + type: 'reply' + }, + 216: { + name: 'rpl_statskline', + type: 'reply' + }, + 218: { + name: 'rpl_statsyline', + type: 'reply' + }, + 219: { + name: 'rpl_endofstats', + type: 'reply' + }, + 221: { + name: 'rpl_umodeis', + type: 'reply' + }, + 241: { + name: 'rpl_statslline', + type: 'reply' + }, + 242: { + name: 'rpl_statsuptime', + type: 'reply' + }, + 243: { + name: 'rpl_statsoline', + type: 'reply' + }, + 244: { + name: 'rpl_statshline', + type: 'reply' + }, + 250: { + name: 'rpl_statsconn', + type: 'reply' + }, + 251: { + name: 'rpl_luserclient', + type: 'reply' + }, + 252: { + name: 'rpl_luserop', + type: 'reply' + }, + 253: { + name: 'rpl_luserunknown', + type: 'reply' + }, + 254: { + name: 'rpl_luserchannels', + type: 'reply' + }, + 255: { + name: 'rpl_luserme', + type: 'reply' + }, + 256: { + name: 'rpl_adminme', + type: 'reply' + }, + 257: { + name: 'rpl_adminloc1', + type: 'reply' + }, + 258: { + name: 'rpl_adminloc2', + type: 'reply' + }, + 259: { + name: 'rpl_adminemail', + type: 'reply' + }, + 261: { + name: 'rpl_tracelog', + type: 'reply' + }, + 265: { + name: 'rpl_localusers', + type: 'reply' + }, + 266: { + name: 'rpl_globalusers', + type: 'reply' + }, + 300: { + name: 'rpl_none', + type: 'reply' + }, + 301: { + name: 'rpl_away', + type: 'reply' + }, + 302: { + name: 'rpl_userhost', + type: 'reply' + }, + 303: { + name: 'rpl_ison', + type: 'reply' + }, + 305: { + name: 'rpl_unaway', + type: 'reply' + }, + 306: { + name: 'rpl_nowaway', + type: 'reply' + }, + 311: { + name: 'rpl_whoisuser', + type: 'reply' + }, + 312: { + name: 'rpl_whoisserver', + type: 'reply' + }, + 313: { + name: 'rpl_whoisoperator', + type: 'reply' + }, + 314: { + name: 'rpl_whowasuser', + type: 'reply' + }, + 315: { + name: 'rpl_endofwho', + type: 'reply' + }, + 317: { + name: 'rpl_whoisidle', + type: 'reply' + }, + 318: { + name: 'rpl_endofwhois', + type: 'reply' + }, + 319: { + name: 'rpl_whoischannels', + type: 'reply' + }, + 321: { + name: 'rpl_liststart', + type: 'reply' + }, + 322: { + name: 'rpl_list', + type: 'reply' + }, + 323: { + name: 'rpl_listend', + type: 'reply' + }, + 324: { + name: 'rpl_channelmodeis', + type: 'reply' + }, + 329: { + name: 'rpl_creationtime', + type: 'reply' + }, + 331: { + name: 'rpl_notopic', + type: 'reply' + }, + 332: { + name: 'rpl_topic', + type: 'reply' + }, + 333: { + name: 'rpl_topicwhotime', + type: 'reply' + }, + 341: { + name: 'rpl_inviting', + type: 'reply' + }, + 342: { + name: 'rpl_summoning', + type: 'reply' + }, + 351: { + name: 'rpl_version', + type: 'reply' + }, + 352: { + name: 'rpl_whoreply', + type: 'reply' + }, + 353: { + name: 'rpl_namreply', + type: 'reply' + }, + 364: { + name: 'rpl_links', + type: 'reply' + }, + 365: { + name: 'rpl_endoflinks', + type: 'reply' + }, + 366: { + name: 'rpl_endofnames', + type: 'reply' + }, + 367: { + name: 'rpl_banlist', + type: 'reply' + }, + 368: { + name: 'rpl_endofbanlist', + type: 'reply' + }, + 369: { + name: 'rpl_endofwhowas', + type: 'reply' + }, + 371: { + name: 'rpl_info', + type: 'reply' + }, + 372: { + name: 'rpl_motd', + type: 'reply' + }, + 374: { + name: 'rpl_endofinfo', + type: 'reply' + }, + 375: { + name: 'rpl_motdstart', + type: 'reply' + }, + 376: { + name: 'rpl_endofmotd', + type: 'reply' + }, + 381: { + name: 'rpl_youreoper', + type: 'reply' + }, + 382: { + name: 'rpl_rehashing', + type: 'reply' + }, + 391: { + name: 'rpl_time', + type: 'reply' + }, + 392: { + name: 'rpl_usersstart', + type: 'reply' + }, + 393: { + name: 'rpl_users', + type: 'reply' + }, + 394: { + name: 'rpl_endofusers', + type: 'reply' + }, + 395: { + name: 'rpl_nousers', + type: 'reply' + }, + 401: { + name: 'err_nosuchnick', + type: 'error' + }, + 402: { + name: 'err_nosuchserver', + type: 'error' + }, + 403: { + name: 'err_nosuchchannel', + type: 'error' + }, + 404: { + name: 'err_cannotsendtochan', + type: 'error' + }, + 405: { + name: 'err_toomanychannels', + type: 'error' + }, + 406: { + name: 'err_wasnosuchnick', + type: 'error' + }, + 407: { + name: 'err_toomanytargets', + type: 'error' + }, + 409: { + name: 'err_noorigin', + type: 'error' + }, + 411: { + name: 'err_norecipient', + type: 'error' + }, + 412: { + name: 'err_notexttosend', + type: 'error' + }, + 413: { + name: 'err_notoplevel', + type: 'error' + }, + 414: { + name: 'err_wildtoplevel', + type: 'error' + }, + 421: { + name: 'err_unknowncommand', + type: 'error' + }, + 422: { + name: 'err_nomotd', + type: 'error' + }, + 423: { + name: 'err_noadmininfo', + type: 'error' + }, + 424: { + name: 'err_fileerror', + type: 'error' + }, + 431: { + name: 'err_nonicknamegiven', + type: 'error' + }, + 432: { + name: 'err_erroneusnickname', + type: 'error' + }, + 433: { + name: 'err_nicknameinuse', + type: 'error' + }, + 436: { + name: 'err_nickcollision', + type: 'error' + }, + 441: { + name: 'err_usernotinchannel', + type: 'error' + }, + 442: { + name: 'err_notonchannel', + type: 'error' + }, + 443: { + name: 'err_useronchannel', + type: 'error' + }, + 444: { + name: 'err_nologin', + type: 'error' + }, + 445: { + name: 'err_summondisabled', + type: 'error' + }, + 446: { + name: 'err_usersdisabled', + type: 'error' + }, + 451: { + name: 'err_notregistered', + type: 'error' + }, + 461: { + name: 'err_needmoreparams', + type: 'error' + }, + 462: { + name: 'err_alreadyregistred', + type: 'error' + }, + 463: { + name: 'err_nopermforhost', + type: 'error' + }, + 464: { + name: 'err_passwdmismatch', + type: 'error' + }, + 465: { + name: 'err_yourebannedcreep', + type: 'error' + }, + 467: { + name: 'err_keyset', + type: 'error' + }, + 471: { + name: 'err_channelisfull', + type: 'error' + }, + 472: { + name: 'err_unknownmode', + type: 'error' + }, + 473: { + name: 'err_inviteonlychan', + type: 'error' + }, + 474: { + name: 'err_bannedfromchan', + type: 'error' + }, + 475: { + name: 'err_badchannelkey', + type: 'error' + }, + 481: { + name: 'err_noprivileges', + type: 'error' + }, + 482: { + name: 'err_chanoprivsneeded', + type: 'error' + }, + 483: { + name: 'err_cantkillserver', + type: 'error' + }, + 491: { + name: 'err_nooperhost', + type: 'error' + }, + 501: { + name: 'err_umodeunknownflag', + type: 'error' + }, + 502: { + name: 'err_usersdontmatch', + type: 'error' + } }; diff --git a/packages/rocketchat-irc/server/servers/RFC2813/index.js b/packages/rocketchat-irc/server/servers/RFC2813/index.js index 232bfbbed3c62..01e24805c5822 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/index.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/index.js @@ -1,162 +1,163 @@ -import _ from 'underscore' -import net from 'net' -import util from 'util' -import { EventEmitter } from 'events' +import net from 'net'; +import util from 'util'; +import { EventEmitter } from 'events'; -import parseMessage from './parseMessage' +import parseMessage from './parseMessage'; -import peerCommandHandlers from './peerCommandHandlers' -import localCommandHandlers from './localCommandHandlers' +import peerCommandHandlers from './peerCommandHandlers'; +import localCommandHandlers from './localCommandHandlers'; class RFC2813 { - constructor(config) { - this.config = config - - // Hold registered state - this.registerSteps = [] - this.isRegistered = false - - // Hold peer server information - this.serverPrefix = null - - // Hold the buffer while receiving - this.receiveBuffer = new Buffer('') - - // Setup socket - this.socket = new net.Socket() - this.socket.setNoDelay() - this.socket.setEncoding('utf-8') - this.socket.setKeepAlive(true) - this.socket.setTimeout(90000) - - this.socket.on('data', this.onReceiveFromPeer.bind(this)) - // this.socket.on('close', this.onClose) - // this.socket.on('timeout', this.onTimeout) - // this.socket.on('error', this.onError) - - this.socket.on('connect', this.onConnect.bind(this)) - this.socket.on('error', (err) => console.log(`[irc][server][err]`, err)) - - // Setup local - this.on('onReceiveFromLocal', this.onReceiveFromLocal.bind(this)) - } - - /** - * Log helper - */ - log(message) { - console.log(`[irc][server] ${message}`) - } - - /** - * Connect - */ - register() { - this.log(`Connecting to @${this.config.server.host}:${this.config.server.port}`) - - this.socket.connect(this.config.server.port, this.config.server.host) - } - - /** - * Setup the server connection - */ - onConnect() { - this.log('Connected! Registering as server...') - - this.write({ - command: 'PASS', - parameters: [ this.config.passwords.local, '0210', 'ngircd' ] - }) - - this.write({ - command: 'SERVER', parameters: [ this.config.server.name ], - trailer: this.config.server.description - }) - } - - /** - * Sends a command message through the socket - */ - write(command) { - let buffer = command.prefix ? `:${command.prefix} ` : '' - buffer += command.command - - if (command.parameters && command.parameters.length > 0) { - buffer += ` ${command.parameters.join(' ')}` - } - - if (command.trailer) { - buffer += ` :${command.trailer}` - } - - this.log(`Sending Command: ${buffer}`) - - return this.socket.write(`${buffer}\r\n`) - } - - /** - * - * - * Peer message handling - * - * - */ - onReceiveFromPeer(chunk) { - if (typeof (chunk) === 'string') { - this.receiveBuffer += chunk - } else { - this.receiveBuffer = Buffer.concat([this.receiveBuffer, chunk]) - } - - var lines = this.receiveBuffer.toString().split(new RegExp('\r\n|\r|\n')) - - // If the buffer does not end with \r\n, more chunks are coming - if (lines.pop()) return - - // Reset the buffer - this.receiveBuffer = new Buffer('') - - lines.forEach((line) => { - if (line.length) { - var parsedMessage = parseMessage(line) - - if (peerCommandHandlers[parsedMessage.command]) { - this.log(`Handling peer message: ${line}`) - - const command = peerCommandHandlers[parsedMessage.command].call(this, parsedMessage) - - if (command) { - this.log(`Emitting peer command to local: ${JSON.stringify(command)}`) - - this.emit('peerCommand', command) - } - - } else { - this.log(`Unhandled peer message: ${JSON.stringify(parsedMessage)}`) - } - } - }) - } - - /** - * - * - * Local message handling - * - * - */ - onReceiveFromLocal(command, parameters) { - if (localCommandHandlers[command]) { - this.log(`Handling local command: ${command}`) - - localCommandHandlers[command].call(this, parameters) - - } else { - this.log(`Unhandled local command: ${JSON.stringify(command)}`) - } - } + constructor(config) { + this.config = config; + + // Hold registered state + this.registerSteps = []; + this.isRegistered = false; + + // Hold peer server information + this.serverPrefix = null; + + // Hold the buffer while receiving + this.receiveBuffer = new Buffer(''); + + // Setup socket + this.socket = new net.Socket(); + this.socket.setNoDelay(); + this.socket.setEncoding('utf-8'); + this.socket.setKeepAlive(true); + this.socket.setTimeout(90000); + + this.socket.on('data', this.onReceiveFromPeer.bind(this)); + // this.socket.on('close', this.onClose) + // this.socket.on('timeout', this.onTimeout) + // this.socket.on('error', this.onError) + + this.socket.on('connect', this.onConnect.bind(this)); + this.socket.on('error', (err) => console.log('[irc][server][err]', err)); + + // Setup local + this.on('onReceiveFromLocal', this.onReceiveFromLocal.bind(this)); + } + + /** + * Log helper + */ + log(message) { + console.log(`[irc][server] ${ message }`); + } + + /** + * Connect + */ + register() { + this.log(`Connecting to @${ this.config.server.host }:${ this.config.server.port }`); + + this.socket.connect(this.config.server.port, this.config.server.host); + } + + /** + * Setup the server connection + */ + onConnect() { + this.log('Connected! Registering as server...'); + + this.write({ + command: 'PASS', + parameters: [ this.config.passwords.local, '0210', 'ngircd' ] + }); + + this.write({ + command: 'SERVER', parameters: [ this.config.server.name ], + trailer: this.config.server.description + }); + } + + /** + * Sends a command message through the socket + */ + write(command) { + let buffer = command.prefix ? `:${ command.prefix } ` : ''; + buffer += command.command; + + if (command.parameters && command.parameters.length > 0) { + buffer += ` ${ command.parameters.join(' ') }`; + } + + if (command.trailer) { + buffer += ` :${ command.trailer }`; + } + + this.log(`Sending Command: ${ buffer }`); + + return this.socket.write(`${ buffer }\r\n`); + } + + /** + * + * + * Peer message handling + * + * + */ + onReceiveFromPeer(chunk) { + if (typeof (chunk) === 'string') { + this.receiveBuffer += chunk; + } else { + this.receiveBuffer = Buffer.concat([this.receiveBuffer, chunk]); + } + + const lines = this.receiveBuffer.toString().split(/\r\n|\r|\n/); + + // If the buffer does not end with \r\n, more chunks are coming + if (lines.pop()) { + return; + } + + // Reset the buffer + this.receiveBuffer = new Buffer(''); + + lines.forEach((line) => { + if (line.length) { + const parsedMessage = parseMessage(line); + + if (peerCommandHandlers[parsedMessage.command]) { + this.log(`Handling peer message: ${ line }`); + + const command = peerCommandHandlers[parsedMessage.command].call(this, parsedMessage); + + if (command) { + this.log(`Emitting peer command to local: ${ JSON.stringify(command) }`); + + this.emit('peerCommand', command); + } + + } else { + this.log(`Unhandled peer message: ${ JSON.stringify(parsedMessage) }`); + } + } + }); + } + + /** + * + * + * Local message handling + * + * + */ + onReceiveFromLocal(command, parameters) { + if (localCommandHandlers[command]) { + this.log(`Handling local command: ${ command }`); + + localCommandHandlers[command].call(this, parameters); + + } else { + this.log(`Unhandled local command: ${ JSON.stringify(command) }`); + } + } } -util.inherits(RFC2813, EventEmitter) +util.inherits(RFC2813, EventEmitter); -export default RFC2813 +export default RFC2813; diff --git a/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js b/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js index 7a5ca783e0b93..83ddae97d44db 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js @@ -1,74 +1,73 @@ export default { - registerUser: function (parameters) { - const { name, profile: { irc: { nick, username } } } = parameters + registerUser: (parameters) => { + const { name, profile: { irc: { nick, username } } } = parameters; - this.write({ - prefix: this.config.server.name, - command: 'NICK', parameters: [ nick, 1, username, 'irc.rocket.chat', 1, '+i' ], - trailer: name - }) - }, + this.write({ + prefix: this.config.server.name, + command: 'NICK', parameters: [ nick, 1, username, 'irc.rocket.chat', 1, '+i' ], + trailer: name + }); + }, - joinChannel: function (parameters) { - const { - room: { name: roomName }, - user: { profile: { irc: { nick } } } - } = parameters + joinChannel: (parameters) => { + const { + room: { name: roomName }, + user: { profile: { irc: { nick } } } + } = parameters; - this.write({ - prefix: this.config.server.name, - command: 'NJOIN', parameters: [ `#${roomName}` ], - trailer: nick - }) - }, + this.write({ + prefix: this.config.server.name, + command: 'NJOIN', parameters: [ `#${ roomName }` ], + trailer: nick + }); + }, - joinedChannel: function (parameters) { - const { - room: { name: roomName }, - user: { profile: { irc: { nick } } } - } = parameters + joinedChannel: (parameters) => { + const { + room: { name: roomName }, + user: { profile: { irc: { nick } } } + } = parameters; - this.write({ - prefix: nick, - command: 'JOIN', parameters: [ `#${roomName}` ] - }) - }, + this.write({ + prefix: nick, + command: 'JOIN', parameters: [ `#${ roomName }` ] + }); + }, - leftChannel: function (parameters) { - const { - room: { name: roomName }, - user: { profile: { irc: { nick } } } - } = parameters + leftChannel: (parameters) => { + const { + room: { name: roomName }, + user: { profile: { irc: { nick } } } + } = parameters; - this.write({ - prefix: nick, - command: 'PART', parameters: [ `#${roomName}` ] - }) - }, + this.write({ + prefix: nick, + command: 'PART', parameters: [ `#${ roomName }` ] + }); + }, - sentMessage: function (parameters) { - const { - user: { profile: { irc: { nick } } }, - to, - message - } = parameters + sentMessage: (parameters) => { + const { + user: { profile: { irc: { nick } } }, + to, + message + } = parameters; - this.write({ - prefix: nick, - command: 'PRIVMSG', parameters: [ to ], - trailer: message - }) - }, + this.write({ + prefix: nick, + command: 'PRIVMSG', parameters: [ to ], + trailer: message + }); + }, - disconnected: function (parameters) { - const { - user: { profile: { irc: { nick } } } - } = parameters + disconnected: (parameters) => { + const { + user: { profile: { irc: { nick } } } + } = parameters; - this.write({ - prefix: nick, - command: 'QUIT' - }) - } - -} + this.write({ + prefix: nick, + command: 'QUIT' + }); + } +}; diff --git a/packages/rocketchat-irc/server/servers/RFC2813/parseMessage.js b/packages/rocketchat-irc/server/servers/RFC2813/parseMessage.js index 9c39709512eae..4199e66972afe 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/parseMessage.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/parseMessage.js @@ -3,7 +3,7 @@ * by https://github.com/martynsmith */ -var replyFor = require('./codes'); +const replyFor = require('./codes'); /** * parseMessage(line, stripColors) @@ -14,55 +14,56 @@ var replyFor = require('./codes'); * @return {Object} A parsed message object. */ module.exports = function parseMessage(line) { - var message = {}; - var match; + const message = {}; + let match; - // Parse prefix - match = line.match(/^:([^ ]+) +/); - if (match) { - message.prefix = match[1]; - line = line.replace(/^:[^ ]+ +/, ''); - match = message.prefix.match(/^([_a-zA-Z0-9\~\[\]\\`^{}|-]*)(!([^@]+)@(.*))?$/); - if (match) { - message.nick = match[1]; - message.user = match[3]; - message.host = match[4]; - } - else { - message.server = message.prefix; - } - } + // Parse prefix + match = line.match(/^:([^ ]+) +/); + if (match) { + message.prefix = match[1]; + line = line.replace(/^:[^ ]+ +/, ''); + match = message.prefix.match(/^([_a-zA-Z0-9\~\[\]\\`^{}|-]*)(!([^@]+)@(.*))?$/); + if (match) { + message.nick = match[1]; + message.user = match[3]; + message.host = match[4]; + } else { + message.server = message.prefix; + } + } - // Parse command - match = line.match(/^([^ ]+) */); - message.command = match[1]; - message.rawCommand = match[1]; - message.commandType = 'normal'; - line = line.replace(/^[^ ]+ +/, ''); + // Parse command + match = line.match(/^([^ ]+) */); + message.command = match[1]; + message.rawCommand = match[1]; + message.commandType = 'normal'; + line = line.replace(/^[^ ]+ +/, ''); - if (replyFor[message.rawCommand]) { - message.command = replyFor[message.rawCommand].name; - message.commandType = replyFor[message.rawCommand].type; - } + if (replyFor[message.rawCommand]) { + message.command = replyFor[message.rawCommand].name; + message.commandType = replyFor[message.rawCommand].type; + } - message.args = []; - var middle, trailing; + message.args = []; + let middle; + let trailing; - // Parse parameters - if (line.search(/^:|\s+:/) != -1) { - match = line.match(/(.*?)(?:^:|\s+:)(.*)/); - middle = match[1].trimRight(); - trailing = match[2]; - } - else { - middle = line; - } + // Parse parameters + if (line.search(/^:|\s+:/) !== -1) { + match = line.match(/(.*?)(?:^:|\s+:)(.*)/); + middle = match[1].trimRight(); + trailing = match[2]; + } else { + middle = line; + } - if (middle.length) - message.args = middle.split(/ +/); + if (middle.length) { + message.args = middle.split(/ +/); + } - if (typeof (trailing) != 'undefined' && trailing.length) - message.args.push(trailing); + if (typeof (trailing) !== 'undefined' && trailing.length) { + message.args.push(trailing); + } - return message; -} + return message; +}; diff --git a/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js b/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js index 241adc33913bc..1036a89bc0a65 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js @@ -1,112 +1,112 @@ export default { - PASS: function (parsedMessage) { - this.log('Received PASS command, continue registering...') - - this.registerSteps.push('PASS') - }, - - SERVER: function (parsedMessage) { - this.log('Received SERVER command, waiting for first PING...') - - this.serverPrefix = parsedMessage.prefix - - this.registerSteps.push('SERVER') - }, - - PING: function (parsedMessage) { - if (!this.isRegistered && this.registerSteps.length === 2) { - this.log('Received first PING command, server is registered!') - - this.isRegistered = true - - this.emit('registered') - } - - this.write({ - prefix: this.config.server.name, - command: 'PONG', - parameters: [ this.config.server.name ] - }) - }, - - NICK: function (parsedMessage) { - let command - - // Check if the message comes from the server, - // which means it is a new user - if (parsedMessage.prefix === this.serverPrefix) { - command = { - identifier: 'userRegistered', - args: { - nick: parsedMessage.args[0], - username: parsedMessage.args[2].substring(1), - host: parsedMessage.args[3], - name: parsedMessage.args[6], - } - } - } else { // Otherwise, it is a nick change - command = { - identifier: 'nickChanged', - args: { - nick: parsedMessage.nick, - newNick: parsedMessage.args[0], - } - } - } - - return command - }, - - JOIN: function (parsedMessage) { - const command = { - identifier: 'joinedChannel', - args: { - roomName: parsedMessage.args[0].substring(1), - nick: parsedMessage.prefix - } - } - - return command - }, - - PART: function (parsedMessage) { - let command = { - identifier: 'leftChannel', - args: { - roomName: parsedMessage.args[0].substring(1), - nick: parsedMessage.prefix - } - } - - return command - }, - - PRIVMSG: function (parsedMessage) { - let command = { - identifier: 'sentMessage', - args: { - nick: parsedMessage.prefix, - message: parsedMessage.args[1] - } - } - - if (parsedMessage.args[0][0] === '#') { - command.args.roomName = parsedMessage.args[0].substring(1) - } else { - command.args.recipientNick = parsedMessage.args[0] - } - - return command - }, - - QUIT: function (parsedMessage) { - let command = { - identifier: 'disconnected', - args: { - nick: parsedMessage.prefix - } - } - - return command - } -} + PASS: () => { + this.log('Received PASS command, continue registering...'); + + this.registerSteps.push('PASS'); + }, + + SERVER: (parsedMessage) => { + this.log('Received SERVER command, waiting for first PING...'); + + this.serverPrefix = parsedMessage.prefix; + + this.registerSteps.push('SERVER'); + }, + + PING: () => { + if (!this.isRegistered && this.registerSteps.length === 2) { + this.log('Received first PING command, server is registered!'); + + this.isRegistered = true; + + this.emit('registered'); + } + + this.write({ + prefix: this.config.server.name, + command: 'PONG', + parameters: [ this.config.server.name ] + }); + }, + + NICK: (parsedMessage) => { + let command; + + // Check if the message comes from the server, + // which means it is a new user + if (parsedMessage.prefix === this.serverPrefix) { + command = { + identifier: 'userRegistered', + args: { + nick: parsedMessage.args[0], + username: parsedMessage.args[2].substring(1), + host: parsedMessage.args[3], + name: parsedMessage.args[6] + } + }; + } else { // Otherwise, it is a nick change + command = { + identifier: 'nickChanged', + args: { + nick: parsedMessage.nick, + newNick: parsedMessage.args[0] + } + }; + } + + return command; + }, + + JOIN: (parsedMessage) => { + const command = { + identifier: 'joinedChannel', + args: { + roomName: parsedMessage.args[0].substring(1), + nick: parsedMessage.prefix + } + }; + + return command; + }, + + PART: (parsedMessage) => { + const command = { + identifier: 'leftChannel', + args: { + roomName: parsedMessage.args[0].substring(1), + nick: parsedMessage.prefix + } + }; + + return command; + }, + + PRIVMSG: (parsedMessage) => { + const command = { + identifier: 'sentMessage', + args: { + nick: parsedMessage.prefix, + message: parsedMessage.args[1] + } + }; + + if (parsedMessage.args[0][0] === '#') { + command.args.roomName = parsedMessage.args[0].substring(1); + } else { + command.args.recipientNick = parsedMessage.args[0]; + } + + return command; + }, + + QUIT: (parsedMessage) => { + const command = { + identifier: 'disconnected', + args: { + nick: parsedMessage.prefix + } + }; + + return command; + } +}; diff --git a/packages/rocketchat-irc/server/servers/index.js b/packages/rocketchat-irc/server/servers/index.js index be54ec69c0cbd..6ab8fd6b45940 100644 --- a/packages/rocketchat-irc/server/servers/index.js +++ b/packages/rocketchat-irc/server/servers/index.js @@ -1 +1,3 @@ -export RFC2813 from './RFC2813' +import RFC2813 from './RFC2813'; + +export { RFC2813 }; From e582856c8c84db3e8db843e614327dca282ab781 Mon Sep 17 00:00:00 2001 From: Hudell Date: Tue, 15 May 2018 14:35:05 -0300 Subject: [PATCH 19/26] Fixed partial username --- .../server/servers/RFC2813/peerCommandHandlers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js b/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js index 1036a89bc0a65..4336889e9dbc0 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js @@ -39,7 +39,7 @@ export default { identifier: 'userRegistered', args: { nick: parsedMessage.args[0], - username: parsedMessage.args[2].substring(1), + username: parsedMessage.args[2], host: parsedMessage.args[3], name: parsedMessage.args[6] } From cbd54182f12b5551a4e44d1d16c26d9a9cf6d46d Mon Sep 17 00:00:00 2001 From: Hudell Date: Tue, 15 May 2018 14:51:37 -0300 Subject: [PATCH 20/26] Fixed problems with scope --- .../servers/RFC2813/localCommandHandlers.js | 124 ++++++------ .../servers/RFC2813/peerCommandHandlers.js | 180 +++++++++--------- 2 files changed, 152 insertions(+), 152 deletions(-) diff --git a/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js b/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js index 83ddae97d44db..5f5c6640ee3f2 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/localCommandHandlers.js @@ -1,73 +1,73 @@ -export default { - registerUser: (parameters) => { - const { name, profile: { irc: { nick, username } } } = parameters; +function registerUser(parameters) { + const { name, profile: { irc: { nick, username } } } = parameters; - this.write({ - prefix: this.config.server.name, - command: 'NICK', parameters: [ nick, 1, username, 'irc.rocket.chat', 1, '+i' ], - trailer: name - }); - }, + this.write({ + prefix: this.config.server.name, + command: 'NICK', parameters: [ nick, 1, username, 'irc.rocket.chat', 1, '+i' ], + trailer: name + }); +} - joinChannel: (parameters) => { - const { - room: { name: roomName }, - user: { profile: { irc: { nick } } } - } = parameters; +function joinChannel(parameters) { + const { + room: { name: roomName }, + user: { profile: { irc: { nick } } } + } = parameters; - this.write({ - prefix: this.config.server.name, - command: 'NJOIN', parameters: [ `#${ roomName }` ], - trailer: nick - }); - }, + this.write({ + prefix: this.config.server.name, + command: 'NJOIN', parameters: [ `#${ roomName }` ], + trailer: nick + }); +} - joinedChannel: (parameters) => { - const { - room: { name: roomName }, - user: { profile: { irc: { nick } } } - } = parameters; +function joinedChannel(parameters) { + const { + room: { name: roomName }, + user: { profile: { irc: { nick } } } + } = parameters; - this.write({ - prefix: nick, - command: 'JOIN', parameters: [ `#${ roomName }` ] - }); - }, + this.write({ + prefix: nick, + command: 'JOIN', parameters: [ `#${ roomName }` ] + }); +} - leftChannel: (parameters) => { - const { - room: { name: roomName }, - user: { profile: { irc: { nick } } } - } = parameters; +function leftChannel(parameters) { + const { + room: { name: roomName }, + user: { profile: { irc: { nick } } } + } = parameters; - this.write({ - prefix: nick, - command: 'PART', parameters: [ `#${ roomName }` ] - }); - }, + this.write({ + prefix: nick, + command: 'PART', parameters: [ `#${ roomName }` ] + }); +} - sentMessage: (parameters) => { - const { - user: { profile: { irc: { nick } } }, - to, - message - } = parameters; +function sentMessage(parameters) { + const { + user: { profile: { irc: { nick } } }, + to, + message + } = parameters; - this.write({ - prefix: nick, - command: 'PRIVMSG', parameters: [ to ], - trailer: message - }); - }, + this.write({ + prefix: nick, + command: 'PRIVMSG', parameters: [ to ], + trailer: message + }); +} - disconnected: (parameters) => { - const { - user: { profile: { irc: { nick } } } - } = parameters; +function disconnected(parameters) { + const { + user: { profile: { irc: { nick } } } + } = parameters; - this.write({ - prefix: nick, - command: 'QUIT' - }); - } -}; + this.write({ + prefix: nick, + command: 'QUIT' + }); +} + +export default { registerUser, joinChannel, joinedChannel, leftChannel, sentMessage, disconnected }; diff --git a/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js b/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js index 4336889e9dbc0..f463be3de976d 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/peerCommandHandlers.js @@ -1,112 +1,112 @@ -export default { - PASS: () => { - this.log('Received PASS command, continue registering...'); +function PASS() { + this.log('Received PASS command, continue registering...'); - this.registerSteps.push('PASS'); - }, + this.registerSteps.push('PASS'); +} - SERVER: (parsedMessage) => { - this.log('Received SERVER command, waiting for first PING...'); +function SERVER(parsedMessage) { + this.log('Received SERVER command, waiting for first PING...'); - this.serverPrefix = parsedMessage.prefix; + this.serverPrefix = parsedMessage.prefix; - this.registerSteps.push('SERVER'); - }, + this.registerSteps.push('SERVER'); +} - PING: () => { - if (!this.isRegistered && this.registerSteps.length === 2) { - this.log('Received first PING command, server is registered!'); +function PING() { + if (!this.isRegistered && this.registerSteps.length === 2) { + this.log('Received first PING command, server is registered!'); - this.isRegistered = true; + this.isRegistered = true; - this.emit('registered'); - } - - this.write({ - prefix: this.config.server.name, - command: 'PONG', - parameters: [ this.config.server.name ] - }); - }, - - NICK: (parsedMessage) => { - let command; - - // Check if the message comes from the server, - // which means it is a new user - if (parsedMessage.prefix === this.serverPrefix) { - command = { - identifier: 'userRegistered', - args: { - nick: parsedMessage.args[0], - username: parsedMessage.args[2], - host: parsedMessage.args[3], - name: parsedMessage.args[6] - } - }; - } else { // Otherwise, it is a nick change - command = { - identifier: 'nickChanged', - args: { - nick: parsedMessage.nick, - newNick: parsedMessage.args[0] - } - }; - } - - return command; - }, + this.emit('registered'); + } - JOIN: (parsedMessage) => { - const command = { - identifier: 'joinedChannel', + this.write({ + prefix: this.config.server.name, + command: 'PONG', + parameters: [ this.config.server.name ] + }); +} + +function NICK(parsedMessage) { + let command; + + // Check if the message comes from the server, + // which means it is a new user + if (parsedMessage.prefix === this.serverPrefix) { + command = { + identifier: 'userRegistered', args: { - roomName: parsedMessage.args[0].substring(1), - nick: parsedMessage.prefix + nick: parsedMessage.args[0], + username: parsedMessage.args[2], + host: parsedMessage.args[3], + name: parsedMessage.args[6] } }; - - return command; - }, - - PART: (parsedMessage) => { - const command = { - identifier: 'leftChannel', + } else { // Otherwise, it is a nick change + command = { + identifier: 'nickChanged', args: { - roomName: parsedMessage.args[0].substring(1), - nick: parsedMessage.prefix + nick: parsedMessage.nick, + newNick: parsedMessage.args[0] } }; + } - return command; - }, + return command; +} - PRIVMSG: (parsedMessage) => { - const command = { - identifier: 'sentMessage', - args: { - nick: parsedMessage.prefix, - message: parsedMessage.args[1] - } - }; +function JOIN(parsedMessage) { + const command = { + identifier: 'joinedChannel', + args: { + roomName: parsedMessage.args[0].substring(1), + nick: parsedMessage.prefix + } + }; + + return command; +} - if (parsedMessage.args[0][0] === '#') { - command.args.roomName = parsedMessage.args[0].substring(1); - } else { - command.args.recipientNick = parsedMessage.args[0]; +function PART(parsedMessage) { + const command = { + identifier: 'leftChannel', + args: { + roomName: parsedMessage.args[0].substring(1), + nick: parsedMessage.prefix } + }; - return command; - }, + return command; +} - QUIT: (parsedMessage) => { - const command = { - identifier: 'disconnected', - args: { - nick: parsedMessage.prefix - } - }; +function PRIVMSG(parsedMessage) { + const command = { + identifier: 'sentMessage', + args: { + nick: parsedMessage.prefix, + message: parsedMessage.args[1] + } + }; - return command; + if (parsedMessage.args[0][0] === '#') { + command.args.roomName = parsedMessage.args[0].substring(1); + } else { + command.args.recipientNick = parsedMessage.args[0]; } -}; + + return command; +} + +function QUIT(parsedMessage) { + const command = { + identifier: 'disconnected', + args: { + nick: parsedMessage.prefix + } + }; + + return command; +} + +export default { PASS, SERVER, PING, NICK, JOIN, PART, PRIVMSG, QUIT }; From 77dae32cef2fa4e7c18130153fd38d3e15a32ebd Mon Sep 17 00:00:00 2001 From: Hudell Date: Tue, 15 May 2018 14:57:39 -0300 Subject: [PATCH 21/26] removed parser name --- .eslintrc | 1 - 1 file changed, 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index 63a34f76b1319..32ba25020b8a7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,4 @@ { - "parser": "babel-eslint", "parserOptions": { "sourceType": "module", "ecmaVersion": 2017, From 0678020cbef816164615c4c128f2638054a57c54 Mon Sep 17 00:00:00 2001 From: Hudell Date: Mon, 21 May 2018 14:03:07 -0300 Subject: [PATCH 22/26] Added a button to reset the IRC connection --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-irc/package.js | 1 + .../rocketchat-irc/server/irc-bridge/index.js | 5 +++ .../irc-bridge/peerHandlers/joinedChannel.js | 1 + .../rocketchat-irc/server/irc-settings.js | 8 ++++- packages/rocketchat-irc/server/irc.js | 4 +-- .../server/methods/resetIrcConnection.js | 36 +++++++++++++++++++ .../server/servers/RFC2813/index.js | 30 +++++++++++++--- 8 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 packages/rocketchat-irc/server/methods/resetIrcConnection.js diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 34bbacfe2a7ca..6dced9276362a 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1745,6 +1745,7 @@ "Reset": "Reset", "Reset_password": "Reset password", "Reset_section_settings": "Reset Section Settings", + "Reset_Connection" : "Reset Connection", "Restart": "Restart", "Restart_the_server": "Restart the server", "Retail": "Retail", diff --git a/packages/rocketchat-irc/package.js b/packages/rocketchat-irc/package.js index 0b9be6f5d5eb4..6072d44d9f863 100644 --- a/packages/rocketchat-irc/package.js +++ b/packages/rocketchat-irc/package.js @@ -13,6 +13,7 @@ Package.onUse(function(api) { ]); api.addFiles('server/irc.js', 'server'); + api.addFiles('server/methods/resetIrcConnection.js', 'server'); api.addFiles('server/irc-settings.js', 'server'); }); diff --git a/packages/rocketchat-irc/server/irc-bridge/index.js b/packages/rocketchat-irc/server/irc-bridge/index.js index 69c8df9453786..4382dd0e35c17 100644 --- a/packages/rocketchat-irc/server/irc-bridge/index.js +++ b/packages/rocketchat-irc/server/irc-bridge/index.js @@ -25,6 +25,7 @@ class Bridge { } init() { + this.loggedInUsers = []; this.server.register(); this.server.on('registered', () => { @@ -34,6 +35,10 @@ class Bridge { }); } + stop() { + this.server.disconnect(); + } + /** * Log helper */ diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js index 1dfae5873f294..94b05080d8b0b 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js @@ -10,6 +10,7 @@ export default function handleJoinedChannel(args) { let room = RocketChat.models.Rooms.findOneByName(args.roomName); if (!room) { + console.log(args); const createdRoom = RocketChat.createRoom('c', args.roomName, user.username, [ /* usernames of the participants here */]); room = RocketChat.models.Rooms.findOne({ _id: createdRoom.rid }); diff --git a/packages/rocketchat-irc/server/irc-settings.js b/packages/rocketchat-irc/server/irc-settings.js index b452718345bb4..32e7033b15d4b 100644 --- a/packages/rocketchat-irc/server/irc-settings.js +++ b/packages/rocketchat-irc/server/irc-settings.js @@ -1,5 +1,5 @@ Meteor.startup(function() { - RocketChat.settings.addGroup('IRC', function() { + RocketChat.settings.addGroup('IRC Federation', function() { this.add('IRC_Enabled', false, { type: 'boolean', i18nLabel: 'Enabled', @@ -53,5 +53,11 @@ Meteor.startup(function() { i18nLabel: 'Peer_Password', i18nDescription: 'IRC_Peer_Password' }); + + this.add('IRC_Reset_Connection', 'resetIrcConnection', { + type: 'action', + actionText: 'Reset_Connection', + i18nLabel: 'Reset_Connection' + }); }); }); diff --git a/packages/rocketchat-irc/server/irc.js b/packages/rocketchat-irc/server/irc.js index ffdb0bcdc9a29..0b1a742f0a3ad 100644 --- a/packages/rocketchat-irc/server/irc.js +++ b/packages/rocketchat-irc/server/irc.js @@ -16,9 +16,9 @@ if (!!RocketChat.settings.get('IRC_Enabled') === true) { } }; - const bridge = new Bridge(config); + Meteor.ircBridge = new Bridge(config); Meteor.startup(() => { - bridge.init(); + Meteor.ircBridge.init(); }); } diff --git a/packages/rocketchat-irc/server/methods/resetIrcConnection.js b/packages/rocketchat-irc/server/methods/resetIrcConnection.js new file mode 100644 index 0000000000000..0dc39abc63902 --- /dev/null +++ b/packages/rocketchat-irc/server/methods/resetIrcConnection.js @@ -0,0 +1,36 @@ +import Bridge from '../irc-bridge'; + +Meteor.methods({ + resetIrcConnection() { + if (!!RocketChat.settings.get('IRC_Enabled') === true) { + if (Meteor.ircBridge) { + Meteor.ircBridge.init(); + return true; + } + + // Normalize the config values + const config = { + server: { + protocol: RocketChat.settings.get('IRC_Protocol'), + host: RocketChat.settings.get('IRC_Host'), + port: RocketChat.settings.get('IRC_Port'), + name: RocketChat.settings.get('IRC_Name'), + description: RocketChat.settings.get('IRC_Description') + }, + passwords: { + local: RocketChat.settings.get('IRC_Local_Password'), + peer: RocketChat.settings.get('IRC_Peer_Password') + } + }; + + Meteor.ircBridge = new Bridge(config); + Meteor.ircBridge.init(); + return true; + } else if (Meteor.ircBridge) { + Meteor.ircBridge.stop(); + return true; + } + + return false; + } +}); diff --git a/packages/rocketchat-irc/server/servers/RFC2813/index.js b/packages/rocketchat-irc/server/servers/RFC2813/index.js index 01e24805c5822..7d38b636c646b 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/index.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/index.js @@ -21,6 +21,12 @@ class RFC2813 { // Hold the buffer while receiving this.receiveBuffer = new Buffer(''); + } + + /** + * Setup socket + */ + setupSocket() { // Setup socket this.socket = new net.Socket(); this.socket.setNoDelay(); @@ -29,13 +35,11 @@ class RFC2813 { this.socket.setTimeout(90000); this.socket.on('data', this.onReceiveFromPeer.bind(this)); - // this.socket.on('close', this.onClose) - // this.socket.on('timeout', this.onTimeout) - // this.socket.on('error', this.onError) this.socket.on('connect', this.onConnect.bind(this)); this.socket.on('error', (err) => console.log('[irc][server][err]', err)); - + this.socket.on('timeout', () => this.log('Timeout')); + this.socket.on('close', () => this.log('Connection Closed')); // Setup local this.on('onReceiveFromLocal', this.onReceiveFromLocal.bind(this)); } @@ -53,9 +57,27 @@ class RFC2813 { register() { this.log(`Connecting to @${ this.config.server.host }:${ this.config.server.port }`); + if (!this.socket) { + this.setupSocket(); + } + this.socket.connect(this.config.server.port, this.config.server.host); } + /** + * Disconnect + */ + disconnect() { + this.log('Disconnecting from server.'); + + if (this.socket) { + this.socket.destroy(); + this.socket = undefined; + } + this.isRegistered = false; + this.registerSteps = []; + } + /** * Setup the server connection */ From 73cbd781b15bd5f00fa378afdcae782e2d063e73 Mon Sep 17 00:00:00 2001 From: Hudell Date: Mon, 21 May 2018 14:19:36 -0300 Subject: [PATCH 23/26] Adjusted messages --- packages/rocketchat-i18n/i18n/en.i18n.json | 4 ++++ .../server/methods/resetIrcConnection.js | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 6dced9276362a..8e37c9b6ab6cc 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -507,6 +507,8 @@ "Compact": "Compact", "Computer": "Computer", "Confirm_password": "Confirm your password", + "Connection_Closed" : "Connection closed", + "Connection_Reset" : "Connection reset", "Consulting": "Consulting", "Consumer_Goods": "Consumer Goods", "Content": "Content", @@ -1091,6 +1093,8 @@ "IRC_Channel_Users_End": "End of output of the NAMES command.", "IRC_Description": "Internet Relay Chat (IRC) is a text-based group communication tool. Users join uniquely named channels, or rooms, for open discussion. IRC also supports private messages between individual users and file sharing capabilities. This package integrates these layers of functionality with Rocket.Chat.", "IRC_Enabled": "Attempt to integrate IRC support. Changing this value requires restarting Rocket.Chat.", + "IRC_Federation": "IRC Federation", + "IRC_Federation_Disabled": "IRC Federation is disabled.", "IRC_Hostname": "The IRC host server to connect to.", "IRC_Login_Fail": "Output upon a failed connection to the IRC server.", "IRC_Login_Success": "Output upon a successful connection to the IRC server.", diff --git a/packages/rocketchat-irc/server/methods/resetIrcConnection.js b/packages/rocketchat-irc/server/methods/resetIrcConnection.js index 0dc39abc63902..5fd91b44106f7 100644 --- a/packages/rocketchat-irc/server/methods/resetIrcConnection.js +++ b/packages/rocketchat-irc/server/methods/resetIrcConnection.js @@ -5,7 +5,10 @@ Meteor.methods({ if (!!RocketChat.settings.get('IRC_Enabled') === true) { if (Meteor.ircBridge) { Meteor.ircBridge.init(); - return true; + return { + message: 'Connection_Reset', + params: [] + }; } // Normalize the config values @@ -25,12 +28,19 @@ Meteor.methods({ Meteor.ircBridge = new Bridge(config); Meteor.ircBridge.init(); - return true; + + return { + message: 'Connection_Reset', + params: [] + }; } else if (Meteor.ircBridge) { Meteor.ircBridge.stop(); - return true; + return { + message: 'Connection_Closed', + params: [] + }; } - return false; + throw new Meteor.Error(t('IRC_Federation_Disabled')); } }); From 79415ac70cdae47928399af07020c24faabccf45 Mon Sep 17 00:00:00 2001 From: Pierre Date: Fri, 25 May 2018 01:57:43 -0300 Subject: [PATCH 24/26] Fixed IRC federation for new users --- .../rocketchat-irc/server/irc-bridge/index.js | 1 + .../server/irc-bridge/localHandlers/index.js | 3 +- .../irc-bridge/localHandlers/onCreateUser.js | 32 +++++++++++++++++++ .../irc-bridge/localHandlers/onLogin.js | 10 ++++-- .../irc-bridge/localHandlers/onSaveMessage.js | 24 +++++++++++--- .../irc-bridge/peerHandlers/joinedChannel.js | 1 - .../irc-bridge/peerHandlers/sentMessage.js | 14 ++++++++ .../rocketchat-irc/server/irc-settings.js | 2 +- .../server/methods/resetIrcConnection.js | 20 ++++++++---- .../server/servers/RFC2813/index.js | 6 ++-- 10 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateUser.js diff --git a/packages/rocketchat-irc/server/irc-bridge/index.js b/packages/rocketchat-irc/server/irc-bridge/index.js index 4382dd0e35c17..be146555cefe7 100644 --- a/packages/rocketchat-irc/server/irc-bridge/index.js +++ b/packages/rocketchat-irc/server/irc-bridge/index.js @@ -117,6 +117,7 @@ class Bridge { setupLocalHandlers() { // Auth RocketChat.callbacks.add('afterValidateLogin', this.onMessageReceived.bind(this, 'local', 'onLogin'), RocketChat.callbacks.priority.LOW, 'irc-on-login'); + RocketChat.callbacks.add('afterCreateUser', this.onMessageReceived.bind(this, 'local', 'onCreateUser'), RocketChat.callbacks.priority.LOW, 'irc-on-create-user'); // Joining rooms or channels RocketChat.callbacks.add('afterCreateChannel', this.onMessageReceived.bind(this, 'local', 'onCreateRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-create-channel'); RocketChat.callbacks.add('afterCreateRoom', this.onMessageReceived.bind(this, 'local', 'onCreateRoom'), RocketChat.callbacks.priority.LOW, 'irc-on-create-room'); diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js index 7ca62f5544919..fcc046ebfcd21 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/index.js @@ -4,5 +4,6 @@ import onLeaveRoom from './onLeaveRoom'; import onLogin from './onLogin'; import onLogout from './onLogout'; import onSaveMessage from './onSaveMessage'; +import onCreateUser from './onCreateUser'; -export { onCreateRoom, onJoinRoom, onLeaveRoom, onLogin, onLogout, onSaveMessage }; +export { onCreateRoom, onJoinRoom, onLeaveRoom, onLogin, onLogout, onSaveMessage, onCreateUser }; diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateUser.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateUser.js new file mode 100644 index 0000000000000..ca4366a505edd --- /dev/null +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onCreateUser.js @@ -0,0 +1,32 @@ +export default function handleOnCreateUser(newUser) { + if (!newUser) { + return this.log('Invalid handleOnCreateUser call'); + } + if (!newUser.username) { + return this.log('Invalid handleOnCreateUser call (Missing username)'); + } + if (this.loggedInUsers.indexOf(newUser._id) !== -1) { + return this.log('Duplicate handleOnCreateUser call'); + } + + this.loggedInUsers.push(newUser._id); + + Meteor.users.update({ _id: newUser._id }, { + $set: { + 'profile.irc.fromIRC': false, + 'profile.irc.username': `${ newUser.username }-rkt`, + 'profile.irc.nick': `${ newUser.username }-rkt`, + 'profile.irc.hostname': 'rocket.chat' + } + }); + + const user = RocketChat.models.Users.findOne({ + _id: newUser._id + }); + + this.sendCommand('registerUser', user); + + const rooms = RocketChat.models.Rooms.findWithUsername(user.username).fetch(); + + rooms.forEach(room => this.sendCommand('joinedChannel', { room, user })); +} diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js index 8680e9f509ca0..7b4f918a7021f 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onLogin.js @@ -1,6 +1,12 @@ export default function handleOnLogin(login) { - if (login.user === null || this.loggedInUsers.indexOf(login.user._id) !== -1) { - return this.log('Invalid or duplicate handleOnLogin call'); + if (login.user === null) { + return this.log('Invalid handleOnLogin call'); + } + if (!login.user.username) { + return this.log('Invalid handleOnLogin call (Missing username)'); + } + if (this.loggedInUsers.indexOf(login.user._id) !== -1) { + return this.log('Duplicate handleOnLogin call'); } this.loggedInUsers.push(login.user._id); diff --git a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js index 6c937fd057910..ebfea53dc1b8e 100644 --- a/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js +++ b/packages/rocketchat-irc/server/irc-bridge/localHandlers/onSaveMessage.js @@ -1,13 +1,27 @@ -import _ from 'underscore'; - export default function handleOnSaveMessage(message, to) { let toIdentification = ''; - // Direct message if (to.t === 'd') { - const recipientUser = RocketChat.models.Users.findOne({ username: _.without(to.usernames, to.username)[0] }); + const subscriptions = RocketChat.models.Subscriptions.findByRoomId(to._id); + subscriptions.forEach((subscription) => { + if (subscription.u.username !== to.username) { + const userData = RocketChat.models.Users.findOne({ username: subscription.u.username }); + if (userData) { + if (userData.profile && userData.profile.irc && userData.profile.irc.nick) { + toIdentification = userData.profile.irc.nick; + } else { + toIdentification = userData.username; + } + } else { + toIdentification = subscription.u.username; + } + } + }); - toIdentification = recipientUser.profile.irc.nick; + if (!toIdentification) { + console.error('[irc][server] Target user not found'); + return; + } } else { toIdentification = `#${ to.name }`; } diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js index 94b05080d8b0b..1dfae5873f294 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/joinedChannel.js @@ -10,7 +10,6 @@ export default function handleJoinedChannel(args) { let room = RocketChat.models.Rooms.findOneByName(args.roomName); if (!room) { - console.log(args); const createdRoom = RocketChat.createRoom('c', args.roomName, user.username, [ /* usernames of the participants here */]); room = RocketChat.models.Rooms.findOne({ _id: createdRoom.rid }); diff --git a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js index 3bad240600681..e0649026a72e2 100644 --- a/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js +++ b/packages/rocketchat-irc/server/irc-bridge/peerHandlers/sentMessage.js @@ -32,6 +32,20 @@ const getDirectRoom = (source, target) => { } }); + RocketChat.models.Subscriptions.upsert({rid, 'u._id': source._id}, { + $setOnInsert: { + name: target.username, + t: 'd', + open: false, + alert: false, + unread: 0, + u: { + _id: source._id, + username: source.username + } + } + }); + return { _id: rid, t: 'd' diff --git a/packages/rocketchat-irc/server/irc-settings.js b/packages/rocketchat-irc/server/irc-settings.js index 32e7033b15d4b..e3aa66f7496bc 100644 --- a/packages/rocketchat-irc/server/irc-settings.js +++ b/packages/rocketchat-irc/server/irc-settings.js @@ -1,5 +1,5 @@ Meteor.startup(function() { - RocketChat.settings.addGroup('IRC Federation', function() { + RocketChat.settings.addGroup('IRC', function() { this.add('IRC_Enabled', false, { type: 'boolean', i18nLabel: 'Enabled', diff --git a/packages/rocketchat-irc/server/methods/resetIrcConnection.js b/packages/rocketchat-irc/server/methods/resetIrcConnection.js index 5fd91b44106f7..8cb3b0695c7c5 100644 --- a/packages/rocketchat-irc/server/methods/resetIrcConnection.js +++ b/packages/rocketchat-irc/server/methods/resetIrcConnection.js @@ -2,7 +2,19 @@ import Bridge from '../irc-bridge'; Meteor.methods({ resetIrcConnection() { - if (!!RocketChat.settings.get('IRC_Enabled') === true) { + const ircEnabled = (!!RocketChat.settings.get('IRC_Enabled')) === true; + + if (Meteor.ircBridge) { + Meteor.ircBridge.stop(); + if (!ircEnabled) { + return { + message: 'Connection_Closed', + params: [] + }; + } + } + + if (ircEnabled) { if (Meteor.ircBridge) { Meteor.ircBridge.init(); return { @@ -33,12 +45,6 @@ Meteor.methods({ message: 'Connection_Reset', params: [] }; - } else if (Meteor.ircBridge) { - Meteor.ircBridge.stop(); - return { - message: 'Connection_Closed', - params: [] - }; } throw new Meteor.Error(t('IRC_Federation_Disabled')); diff --git a/packages/rocketchat-irc/server/servers/RFC2813/index.js b/packages/rocketchat-irc/server/servers/RFC2813/index.js index 7d38b636c646b..07bd77d9e7898 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/index.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/index.js @@ -129,7 +129,7 @@ class RFC2813 { this.receiveBuffer = Buffer.concat([this.receiveBuffer, chunk]); } - const lines = this.receiveBuffer.toString().split(/\r\n|\r|\n/); + const lines = this.receiveBuffer.toString().split(/\r\n|\r|\n|\u0007/); // If the buffer does not end with \r\n, more chunks are coming if (lines.pop()) { @@ -140,7 +140,7 @@ class RFC2813 { this.receiveBuffer = new Buffer(''); lines.forEach((line) => { - if (line.length) { + if (line.length && !line.startsWith('\a')) { const parsedMessage = parseMessage(line); if (peerCommandHandlers[parsedMessage.command]) { @@ -150,10 +150,8 @@ class RFC2813 { if (command) { this.log(`Emitting peer command to local: ${ JSON.stringify(command) }`); - this.emit('peerCommand', command); } - } else { this.log(`Unhandled peer message: ${ JSON.stringify(parsedMessage) }`); } From 3479de914e940655fc1286e56213f28c0460b92d Mon Sep 17 00:00:00 2001 From: Pierre Date: Fri, 25 May 2018 10:33:19 -0300 Subject: [PATCH 25/26] Ignore eslint about control character on regex --- packages/rocketchat-irc/server/servers/RFC2813/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-irc/server/servers/RFC2813/index.js b/packages/rocketchat-irc/server/servers/RFC2813/index.js index 07bd77d9e7898..69e12c89410b9 100644 --- a/packages/rocketchat-irc/server/servers/RFC2813/index.js +++ b/packages/rocketchat-irc/server/servers/RFC2813/index.js @@ -129,7 +129,7 @@ class RFC2813 { this.receiveBuffer = Buffer.concat([this.receiveBuffer, chunk]); } - const lines = this.receiveBuffer.toString().split(/\r\n|\r|\n|\u0007/); + const lines = this.receiveBuffer.toString().split(/\r\n|\r|\n|\u0007/); // eslint-disable-line no-control-regex // If the buffer does not end with \r\n, more chunks are coming if (lines.pop()) { From 0ab003d10efe14997f66a9650fb08bf6c5fbd635 Mon Sep 17 00:00:00 2001 From: Pierre Date: Fri, 25 May 2018 11:29:53 -0300 Subject: [PATCH 26/26] Adjusted settings strings --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-irc/server/irc-settings.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index e6fcd2e5af537..30352f6c6d6c2 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1112,6 +1112,7 @@ "IRC_Channel_Users_End": "End of output of the NAMES command.", "IRC_Description": "Internet Relay Chat (IRC) is a text-based group communication tool. Users join uniquely named channels, or rooms, for open discussion. IRC also supports private messages between individual users and file sharing capabilities. This package integrates these layers of functionality with Rocket.Chat.", "IRC_Enabled": "Attempt to integrate IRC support. Changing this value requires restarting Rocket.Chat.", + "IRC_Enabled_Alert": "IRC Support is a work in progress. Use on a production system is not recommended at this time.", "IRC_Federation": "IRC Federation", "IRC_Federation_Disabled": "IRC Federation is disabled.", "IRC_Hostname": "The IRC host server to connect to.", diff --git a/packages/rocketchat-irc/server/irc-settings.js b/packages/rocketchat-irc/server/irc-settings.js index e3aa66f7496bc..f6543891cac7a 100644 --- a/packages/rocketchat-irc/server/irc-settings.js +++ b/packages/rocketchat-irc/server/irc-settings.js @@ -1,9 +1,10 @@ Meteor.startup(function() { - RocketChat.settings.addGroup('IRC', function() { + RocketChat.settings.addGroup('IRC_Federation', function() { this.add('IRC_Enabled', false, { type: 'boolean', i18nLabel: 'Enabled', - i18nDescription: 'IRC_Enabled' + i18nDescription: 'IRC_Enabled', + alert: 'IRC_Enabled_Alert' }); this.add('IRC_Protocol', 'RFC2813', {