Merge branch 'develop' of github.com:RocketChat/Rocket.Chat into develop

Conflicts:
	HISTORY.md
pull/2552/head^2
Marcelo Schmidt 10 years ago
commit 514ea56b62
  1. 1
      .docker/develop/Dockerfile
  2. 1
      .docker/latest/Dockerfile
  3. 16
      .meteor/versions
  4. 1
      HISTORY.md
  5. 38
      packages/rocketchat-cas/cas_client.js
  6. 208
      packages/rocketchat-cas/cas_server.js
  7. 2
      packages/rocketchat-channel-settings/client/views/channelSettings.html
  8. 366
      packages/rocketchat-importer-hipchat/server/HipChatImporter.coffee
  9. 512
      packages/rocketchat-importer-slack/server/SlackImporter.coffee
  10. 3
      packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.coffee
  11. 18
      packages/rocketchat-ui-message/message/message.coffee
  12. 2
      packages/rocketchat-ui/views/app/room.html
  13. 4
      server/lib/accounts.coffee

@ -22,6 +22,7 @@ WORKDIR /app/bundle
# needs a mongoinstance - defaults to container linking with alias 'mongo'
ENV MONGO_URL=mongodb://mongo:27017/rocketchat \
HOME=/tmp \
PORT=3000 \
ROOT_URL=http://localhost:3000 \
Accounts_AvatarStorePath=/app/uploads

@ -22,6 +22,7 @@ WORKDIR /app/bundle
# needs a mongoinstance - defaults to container linking with alias 'mongo'
ENV MONGO_URL=mongodb://mongo:27017/rocketchat \
HOME=/tmp \
PORT=3000 \
ROOT_URL=http://localhost:3000 \
Accounts_AvatarStorePath=/app/uploads

@ -40,7 +40,7 @@ ecmascript-runtime@0.2.6
edgee:slingshot@0.7.1
ejson@1.0.7
email@1.0.8
emojione:emojione@2.1.1
emojione:emojione@2.1.2
facebook@1.2.2
fastclick@1.0.7
francocatena:status@1.5.1
@ -101,7 +101,7 @@ mrt:moment@2.8.1
mrt:moment-timezone@0.2.1
mrt:reactive-store@0.0.1
mystor:device-detection@0.2.0
nimble:restivus@0.8.7
nimble:restivus@0.8.9
nooitaf:colors@0.0.3
npm-bcrypt@0.7.8_2
npm-mongo@1.4.39_1
@ -110,11 +110,11 @@ oauth1@1.1.5
oauth2@1.1.5
observe-sequence@1.0.7
ordered-dict@1.0.4
ostrio:cookies@2.0.1
ostrio:cookies@2.0.2
pauli:accounts-linkedin@1.2.0
pauli:linkedin@1.2.0
peerlibrary:aws-sdk@2.0.17_2
peerlibrary:blocking@0.4.3
peerlibrary:aws-sdk@2.2.42_1
peerlibrary:blocking@0.5.2
perak:codemirror@1.2.9
percolate:synced-cron@1.3.0
pntbr:js-yaml-client@0.0.1
@ -198,19 +198,19 @@ service-configuration@1.0.5
session@1.1.1
sha@1.0.4
simple:highlight.js@1.2.0
simple:json-routes@2.0.1
simple:json-routes@2.1.0
smoral:sweetalert@1.1.1
spacebars@1.0.7
spacebars-compiler@1.0.7
srp@1.0.4
standard-minifiers@1.0.2
steffo:meteor-accounts-saml@0.0.1
tap:i18n@1.7.0
tap:i18n@1.8.0
templating@1.1.5
templating-tools@1.0.0
tmeasday:crypto-base@3.1.2
tmeasday:crypto-md5@3.1.2
todda00:friendly-slugs@0.3.6
todda00:friendly-slugs@0.4.0
tracker@1.0.9
twitter@1.1.5
ui@1.0.8

@ -2,6 +2,7 @@
- Fixes #2477: Admin settings, plain-text SMTP password.
- Closes #625: Filter and sorts direct messages and private groups.
- Closes #2172: Accepts markdown for room topic.
- Fixes #2433: Directly linked channel does not load for newly created user
## 0.22.0, 2016-Mar-14

@ -6,7 +6,7 @@ Meteor.loginWithCas = function(callback) {
var popup_width = RocketChat.settings.get("CAS_popup_width");
var popup_height = RocketChat.settings.get("CAS_popup_height");
if (!login_url) {
if (!login_url) {
return;
}
@ -45,25 +45,23 @@ Meteor.loginWithCas = function(callback) {
};
var openCenteredPopup = function(url, width, height) {
var screenX = typeof window.screenX !== 'undefined'
? window.screenX : window.screenLeft;
var screenY = typeof window.screenY !== 'undefined'
? window.screenY : window.screenTop;
var outerWidth = typeof window.outerWidth !== 'undefined'
? window.outerWidth : document.body.clientWidth;
var outerHeight = typeof window.outerHeight !== 'undefined'
? window.outerHeight : (document.body.clientHeight - 22);
// XXX what is the 22?
// Use `outerWidth - width` and `outerHeight - height` for help in
// positioning the popup centered relative to the current window
var left = screenX + (outerWidth - width) / 2;
var top = screenY + (outerHeight - height) / 2;
var features = ('width=' + width + ',height=' + height +
',left=' + left + ',top=' + top + ',scrollbars=yes');
var screenX = typeof window.screenX !== 'undefined' ? window.screenX : window.screenLeft;
var screenY = typeof window.screenY !== 'undefined' ? window.screenY : window.screenTop;
var outerWidth = typeof window.outerWidth !== 'undefined' ? window.outerWidth : document.body.clientWidth;
var outerHeight = typeof window.outerHeight !== 'undefined' ? window.outerHeight : (document.body.clientHeight - 22);
// XXX what is the 22?
var newwindow = window.open(url, 'Login', features);
if (newwindow.focus)
newwindow.focus();
return newwindow;
// Use `outerWidth - width` and `outerHeight - height` for help in
// positioning the popup centered relative to the current window
var left = screenX + (outerWidth - width) / 2;
var top = screenY + (outerHeight - height) / 2;
var features = ('width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',scrollbars=yes');
var newwindow = window.open(url, 'Login', features);
if (newwindow.focus) {
newwindow.focus();
}
return newwindow;
};

@ -8,77 +8,77 @@ RoutePolicy.declare('/_cas/', 'network');
// Listen to incoming OAuth http requests
WebApp.connectHandlers.use(function(req, res, next) {
// Need to create a Fiber since we're using synchronous http calls and nothing
// else is wrapping this in a fiber automatically
Fiber(function () {
middleware(req, res, next);
}).run();
// Need to create a Fiber since we're using synchronous http calls and nothing
// else is wrapping this in a fiber automatically
Fiber(function () {
middleware(req, res, next);
}).run();
});
var middleware = function (req, res, next) {
// Make sure to catch any exceptions because otherwise we'd crash
// the runner
try {
var barePath = req.url.substring(0, req.url.indexOf('?'));
var splitPath = barePath.split('/');
// Any non-cas request will continue down the default
// middlewares.
if (splitPath[1] !== '_cas') {
next();
return;
}
// Make sure to catch any exceptions because otherwise we'd crash
// the runner
try {
var barePath = req.url.substring(0, req.url.indexOf('?'));
var splitPath = barePath.split('/');
// Any non-cas request will continue down the default
// middlewares.
if (splitPath[1] !== '_cas') {
next();
return;
}
// get auth token
var credentialToken = splitPath[2];
if (!credentialToken) {
closePopup(res);
return;
}
// get auth token
var credentialToken = splitPath[2];
if (!credentialToken) {
closePopup(res);
return;
}
// validate ticket
casTicket(req, credentialToken, function() {
closePopup(res);
});
// validate ticket
casTicket(req, credentialToken, function() {
closePopup(res);
});
} catch (err) {
logger.error("Unexpected error : " + err.message);
closePopup(res);
}
} catch (err) {
logger.error("Unexpected error : " + err.message);
closePopup(res);
}
};
var casTicket = function (req, token, callback) {
// get configuration
if (!RocketChat.settings.get("CAS_enabled")) {
logger.error("Got ticket validation request, but CAS is not enabled");
callback();
}
// get ticket and validate.
var parsedUrl = url.parse(req.url, true);
var ticketId = parsedUrl.query.ticket;
var baseUrl = RocketChat.settings.get("CAS_base_url");
logger.debug("Using CAS_base_url: " + baseUrl);
var cas = new CAS({
base_url: baseUrl,
service: Meteor.absoluteUrl() + "_cas/" + token
});
cas.validate(ticketId, function(err, status, username) {
if (err) {
logger.error("error when trying to validate " + err);
} else {
if (status) {
logger.info("Validated user: " + username);
_casCredentialTokens[token] = { id: username };
} else {
logger.error("Unable to validate ticket: " + ticketId);
}
// get configuration
if (!RocketChat.settings.get("CAS_enabled")) {
logger.error("Got ticket validation request, but CAS is not enabled");
callback();
}
callback();
// get ticket and validate.
var parsedUrl = url.parse(req.url, true);
var ticketId = parsedUrl.query.ticket;
var baseUrl = RocketChat.settings.get("CAS_base_url");
logger.debug("Using CAS_base_url: " + baseUrl);
var cas = new CAS({
base_url: baseUrl,
service: Meteor.absoluteUrl() + "_cas/" + token
});
cas.validate(ticketId, function(err, status, username) {
if (err) {
logger.error("error when trying to validate " + err);
} else {
if (status) {
logger.info("Validated user: " + username);
_casCredentialTokens[token] = { id: username };
} else {
logger.error("Unable to validate ticket: " + ticketId);
}
}
callback();
});
return;
@ -91,58 +91,70 @@ var casTicket = function (req, token, callback) {
*/
Accounts.registerLoginHandler(function (options) {
if (!options.cas)
return undefined;
if (!_hasCredential(options.cas.credentialToken)) {
throw new Meteor.Error(Accounts.LoginCancelledError.numericError,
'no matching login attempt found');
}
var result = _retrieveCredential(options.cas.credentialToken);
var options = { profile: { name: result.id } };
logger.debug("Looking up user with username: " + result.id );
var user = Meteor.users.findOne({ 'services.cas.external_id': result.id });
if (user) {
logger.debug("Using existing user for '" + result.id + "' with id: " + user._id);
} else {
var newUser = {
username: result.id,
active: true,
globalRoles: ['user'],
services: {
cas: {
external_id: result.id
if (!options.cas)
return undefined;
if (!_hasCredential(options.cas.credentialToken)) {
throw new Meteor.Error(Accounts.LoginCancelledError.numericError,
'no matching login attempt found');
}
var result = _retrieveCredential(options.cas.credentialToken);
var options = { profile: { name: result.id } };
// Search existing user by its external service id
logger.debug("Looking up user with username: " + result.id );
var user = Meteor.users.findOne({ 'services.cas.external_id': result.id });
if (user) {
logger.debug("Using existing user for '" + result.id + "' with id: " + user._id);
} else {
// Define new user
var newUser = {
username: result.id,
active: true,
globalRoles: ['user'],
services: {
cas: {
external_id: result.id
}
}
}
};
};
// Create the user
logger.debug("User '" + result.id + "'does not exist yet, creating it");
var userId = Accounts.insertUserDoc({}, newUser);
logger.debug("User '" + result.id + "'does not exist yet, creating it");
var userId = Accounts.insertUserDoc({}, newUser);
user = Meteor.users.findOne(userId);
logger.debug("Created new user for '" + result.id + "' with id: " + user._id);
}
// Fetch and use it
user = Meteor.users.findOne(userId);
logger.debug("Created new user for '" + result.id + "' with id: " + user._id);
logger.debug('Joining user to default channels');
Meteor.runAsUser(user._id, function() {
Meteor.call('joinDefaultChannels');
});
}
return { userId: user._id };
return { userId: user._id };
});
var _hasCredential = function(credentialToken) {
return _.has(_casCredentialTokens, credentialToken);
return _.has(_casCredentialTokens, credentialToken);
}
/*
* Retrieve token and delete it to avoid replaying it.
*/
var _retrieveCredential = function(credentialToken) {
var result = _casCredentialTokens[credentialToken];
delete _casCredentialTokens[credentialToken];
return result;
var result = _casCredentialTokens[credentialToken];
delete _casCredentialTokens[credentialToken];
return result;
}
var closePopup = function(res) {
res.writeHead(200, {'Content-Type': 'text/html'});
var content = '<html><head><script>window.close()</script></head></html>';
res.end(content, 'utf-8');
res.writeHead(200, {'Content-Type': 'text/html'});
var content = '<html><head><script>window.close()</script></head></html>';
res.end(content, 'utf-8');
}

@ -24,7 +24,7 @@
{{#if editing 'roomTopic'}}
<input type="text" name="roomTopic" value="{{roomTopic}}" class="editing" /> <button type="button" class="button secondary cancel">{{_ "Cancel"}}</button> <button type="button" class="button primary save">{{_ "Save"}}</button>
{{else}}
<span>{{roomTopic}}{{#if canEdit}} <i class="octicon octicon-pencil" data-edit="roomTopic"></i>{{/if}}</span>
<span>{{{RocketChatMarkdown roomTopic}}}{{#if canEdit}} <i class="octicon octicon-pencil" data-edit="roomTopic"></i>{{/if}}</span>
{{/if}}
</div>
</li>

@ -9,95 +9,95 @@ Importer.HipChat = class Importer.HipChat extends Importer.Base
prepare: (dataURI, sentContentType, fileName) =>
super(dataURI, sentContentType, fileName)
try
{image, contentType} = RocketChatFile.dataURIParse dataURI
zip = new @AdmZip(new Buffer(image, 'base64'))
zipEntries = zip.getEntries()
tempRooms = []
tempUsers = []
tempMessages = {}
for entry in zipEntries
do (entry) =>
if not entry.isDirectory
if entry.entryName.indexOf(Importer.HipChat.RoomPrefix) > -1
roomName = entry.entryName.split(Importer.HipChat.RoomPrefix)[1]
if roomName is 'list.json'
@updateProgress Importer.ProgressStep.PREPARING_CHANNELS
tempRooms = JSON.parse(entry.getData().toString()).rooms
for room in tempRooms
room.name = _.slugify room.name
else if roomName.indexOf('/') > -1
item = roomName.split('/')
roomName = _.slugify item[0] #random
msgGroupData = item[1].split('.')[0] #2015-10-04
if not tempMessages[roomName]
tempMessages[roomName] = {}
# For some reason some of the json files in the HipChat export aren't valid JSON
# files, so we need to catch those and just ignore them (sadly).
try
tempMessages[roomName][msgGroupData] = JSON.parse entry.getData().toString()
catch
console.warn "#{entry.entryName} is not a valid JSON file! Unable to import it."
else if entry.entryName.indexOf(Importer.HipChat.UsersPrefix) > -1
usersName = entry.entryName.split(Importer.HipChat.UsersPrefix)[1]
if usersName is 'list.json'
@updateProgress Importer.ProgressStep.PREPARING_USERS
tempUsers = JSON.parse(entry.getData().toString()).users
else
console.warn "Unexpected file in the #{@name} import: #{entry.entryName}"
# Insert the users record, eventually this might have to be split into several ones as well
# if someone tries to import a several thousands users instance
usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers }
@users = @collection.findOne usersId
@updateRecord { 'count.users': tempUsers.length }
@addCountToTotal tempUsers.length
# Insert the rooms records.
channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempRooms }
@channels = @collection.findOne channelsId
@updateRecord { 'count.channels': tempRooms.length }
@addCountToTotal tempRooms.length
# Insert the messages records
@updateProgress Importer.ProgressStep.PREPARING_MESSAGES
messagesCount = 0
for channel, messagesObj of tempMessages
do (channel, messagesObj) =>
if not @messages[channel]
@messages[channel] = {}
for date, msgs of messagesObj
messagesCount += msgs.length
@updateRecord { 'messagesstatus': "#{channel}/#{date}" }
if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize
for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs)
messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg }
@messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId
# try
{image, contentType} = RocketChatFile.dataURIParse dataURI
zip = new @AdmZip(new Buffer(image, 'base64'))
zipEntries = zip.getEntries()
tempRooms = []
tempUsers = []
tempMessages = {}
for entry in zipEntries
do (entry) =>
if not entry.isDirectory
if entry.entryName.indexOf(Importer.HipChat.RoomPrefix) > -1
roomName = entry.entryName.split(Importer.HipChat.RoomPrefix)[1]
if roomName is 'list.json'
@updateProgress Importer.ProgressStep.PREPARING_CHANNELS
tempRooms = JSON.parse(entry.getData().toString()).rooms
for room in tempRooms
room.name = _.slugify room.name
else if roomName.indexOf('/') > -1
item = roomName.split('/')
roomName = _.slugify item[0] #random
msgGroupData = item[1].split('.')[0] #2015-10-04
if not tempMessages[roomName]
tempMessages[roomName] = {}
# For some reason some of the json files in the HipChat export aren't valid JSON
# files, so we need to catch those and just ignore them (sadly).
try
tempMessages[roomName][msgGroupData] = JSON.parse entry.getData().toString()
catch
console.warn "#{entry.entryName} is not a valid JSON file! Unable to import it."
else if entry.entryName.indexOf(Importer.HipChat.UsersPrefix) > -1
usersName = entry.entryName.split(Importer.HipChat.UsersPrefix)[1]
if usersName is 'list.json'
@updateProgress Importer.ProgressStep.PREPARING_USERS
tempUsers = JSON.parse(entry.getData().toString()).users
else
messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs }
@messages[channel][date] = @collection.findOne messagesId
@updateRecord { 'count.messages': messagesCount, 'messagesstatus': null }
@addCountToTotal messagesCount
if tempUsers.length is 0 or tempRooms.length is 0 or messagesCount is 0
@updateProgress Importer.ProgressStep.ERROR
return @getProgress()
selectionUsers = tempUsers.map (user) ->
#HipChat's export doesn't contain bot users, from the data I've seen
return new Importer.SelectionUser user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot
selectionChannels = tempRooms.map (room) ->
return new Importer.SelectionChannel room.room_id, room.name, room.is_archived, true
console.warn "Unexpected file in the #{@name} import: #{entry.entryName}"
# Insert the users record, eventually this might have to be split into several ones as well
# if someone tries to import a several thousands users instance
usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers }
@users = @collection.findOne usersId
@updateRecord { 'count.users': tempUsers.length }
@addCountToTotal tempUsers.length
# Insert the rooms records.
channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempRooms }
@channels = @collection.findOne channelsId
@updateRecord { 'count.channels': tempRooms.length }
@addCountToTotal tempRooms.length
# Insert the messages records
@updateProgress Importer.ProgressStep.PREPARING_MESSAGES
messagesCount = 0
for channel, messagesObj of tempMessages
do (channel, messagesObj) =>
if not @messages[channel]
@messages[channel] = {}
for date, msgs of messagesObj
messagesCount += msgs.length
@updateRecord { 'messagesstatus': "#{channel}/#{date}" }
if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize
for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs)
messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg }
@messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId
else
messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs }
@messages[channel][date] = @collection.findOne messagesId
@updateRecord { 'count.messages': messagesCount, 'messagesstatus': null }
@addCountToTotal messagesCount
if tempUsers.length is 0 or tempRooms.length is 0 or messagesCount is 0
@updateProgress Importer.ProgressStep.ERROR
return @getProgress()
selectionUsers = tempUsers.map (user) ->
#HipChat's export doesn't contain bot users, from the data I've seen
return new Importer.SelectionUser user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot
selectionChannels = tempRooms.map (room) ->
return new Importer.SelectionChannel room.room_id, room.name, room.is_archived, true
@updateProgress Importer.ProgressStep.USER_SELECTION
return new Importer.Selection @name, selectionUsers, selectionChannels
catch error
@updateRecord { 'failed': true, 'error': error }
console.error Importer.ProgressStep.ERROR
throw new Error 'import-hipchat-error', error
@updateProgress Importer.ProgressStep.USER_SELECTION
return new Importer.Selection @name, selectionUsers, selectionChannels
# catch error
# @updateRecord { 'failed': true, 'error': error }
# console.error Importer.ProgressStep.ERROR
# throw new Error 'import-hipchat-error', error
startImport: (importSelection) =>
super(importSelection)
@ -115,105 +115,105 @@ Importer.HipChat = class Importer.HipChat extends Importer.Base
startedByUserId = Meteor.userId()
Meteor.defer =>
try
@updateProgress Importer.ProgressStep.IMPORTING_USERS
for user in @users.users when user.do_import
do (user) =>
Meteor.runAsUser startedByUserId, () =>
existantUser = RocketChat.models.Users.findOneByEmailAddress user.email
if existantUser
user.rocketId = existantUser._id
@userTags.push
hipchat: "@#{user.mention_name}"
rocket: "@#{existantUser.username}"
else
userId = Accounts.createUser { email: user.email, password: Date.now() + user.name + user.email.toUpperCase() }
user.rocketId = userId
@userTags.push
hipchat: "@#{user.mention_name}"
rocket: "@#{user.mention_name}"
# try
@updateProgress Importer.ProgressStep.IMPORTING_USERS
for user in @users.users when user.do_import
do (user) =>
Meteor.runAsUser startedByUserId, () =>
existantUser = RocketChat.models.Users.findOneByEmailAddress user.email
if existantUser
user.rocketId = existantUser._id
@userTags.push
hipchat: "@#{user.mention_name}"
rocket: "@#{existantUser.username}"
else
userId = Accounts.createUser { email: user.email, password: Date.now() + user.name + user.email.toUpperCase() }
user.rocketId = userId
@userTags.push
hipchat: "@#{user.mention_name}"
rocket: "@#{user.mention_name}"
Meteor.runAsUser userId, () =>
Meteor.call 'setUsername', user.mention_name
Meteor.call 'joinDefaultChannels', true
Meteor.call 'setAvatarFromService', user.photo_url, null, 'url'
Meteor.call 'updateUserUtcOffset', parseInt moment().tz(user.timezone).format('Z').toString().split(':')[0]
if user.name?
RocketChat.models.Users.setName userId, user.name
#Deleted users are 'inactive' users in Rocket.Chat
if user.is_deleted
Meteor.call 'setUserActiveStatus', userId, false
@addCountCompleted 1
@collection.update { _id: @users._id }, { $set: { 'users': @users.users }}
@updateProgress Importer.ProgressStep.IMPORTING_CHANNELS
for channel in @channels.channels when channel.do_import
do (channel) =>
Meteor.runAsUser startedByUserId, () =>
channel.name = channel.name.replace(/ /g, '')
existantRoom = RocketChat.models.Rooms.findOneByName channel.name
if existantRoom
channel.rocketId = existantRoom._id
else
userId = ''
for user in @users.users when user.user_id is channel.owner_user_id
userId = user.rocketId
if userId isnt ''
Meteor.runAsUser userId, () =>
Meteor.call 'setUsername', user.mention_name
Meteor.call 'joinDefaultChannels', true
Meteor.call 'setAvatarFromService', user.photo_url, null, 'url'
Meteor.call 'updateUserUtcOffset', parseInt moment().tz(user.timezone).format('Z').toString().split(':')[0]
if user.name?
RocketChat.models.Users.setName userId, user.name
#Deleted users are 'inactive' users in Rocket.Chat
if user.is_deleted
Meteor.call 'setUserActiveStatus', userId, false
@addCountCompleted 1
@collection.update { _id: @users._id }, { $set: { 'users': @users.users }}
@updateProgress Importer.ProgressStep.IMPORTING_CHANNELS
for channel in @channels.channels when channel.do_import
do (channel) =>
Meteor.runAsUser startedByUserId, () =>
channel.name = channel.name.replace(/ /g, '')
existantRoom = RocketChat.models.Rooms.findOneByName channel.name
if existantRoom
channel.rocketId = existantRoom._id
returned = Meteor.call 'createChannel', channel.name, []
channel.rocketId = returned.rid
RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: { 'ts': new Date(channel.created * 1000) }}
else
userId = ''
for user in @users.users when user.user_id is channel.owner_user_id
userId = user.rocketId
if userId isnt ''
Meteor.runAsUser userId, () =>
returned = Meteor.call 'createChannel', channel.name, []
channel.rocketId = returned.rid
RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: { 'ts': new Date(channel.created * 1000) }}
else
console.warn "Failed to find the channel creator for #{channel.name}."
@addCountCompleted 1
@collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }}
@updateProgress Importer.ProgressStep.IMPORTING_MESSAGES
nousers = {};
for channel, messagesObj of @messages
do (channel, messagesObj) =>
Meteor.runAsUser startedByUserId, () =>
hipchatChannel = @getHipChatChannelFromName channel
if hipchatChannel?.do_import
room = RocketChat.models.Rooms.findOneById hipchatChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } }
for date, msgs of messagesObj
@updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" }
for message in msgs.messages
if message.from?
user = @getRocketUser(message.from.user_id)
if user?
msgObj =
msg: @convertHipChatMessageToRocketChat(message.message)
ts: new Date(message.date)
u:
_id: user._id
username: user.username
RocketChat.sendMessage user, msgObj, room
else
if not nousers[message.from.user_id]
nousers[message.from.user_id] = message.from
console.warn "Failed to find the channel creator for #{channel.name}."
@addCountCompleted 1
@collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }}
@updateProgress Importer.ProgressStep.IMPORTING_MESSAGES
nousers = {};
for channel, messagesObj of @messages
do (channel, messagesObj) =>
Meteor.runAsUser startedByUserId, () =>
hipchatChannel = @getHipChatChannelFromName channel
if hipchatChannel?.do_import
room = RocketChat.models.Rooms.findOneById hipchatChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } }
for date, msgs of messagesObj
@updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" }
for message in msgs.messages
if message.from?
user = @getRocketUser(message.from.user_id)
if user?
msgObj =
msg: @convertHipChatMessageToRocketChat(message.message)
ts: new Date(message.date)
u:
_id: user._id
username: user.username
RocketChat.sendMessage user, msgObj, room
else
if not _.isArray message
console.warn 'Please report the following:', message
@addCountCompleted 1
console.warn 'The following did not have users:', nousers
@updateProgress Importer.ProgressStep.FINISHING
for channel in @channels.channels when channel.do_import and channel.is_archived
do (channel) =>
Meteor.runAsUser startedByUserId, () =>
Meteor.call 'archiveRoom', channel.rocketId
@updateProgress Importer.ProgressStep.DONE
timeTook = Date.now() - start
console.log "Import took #{timeTook} milliseconds."
catch error
@updateRecord { 'failed': true, 'error': error }
console.error Importer.ProgressStep.ERROR
throw new Error 'import-hipchat-error', error
if not nousers[message.from.user_id]
nousers[message.from.user_id] = message.from
else
if not _.isArray message
console.warn 'Please report the following:', message
@addCountCompleted 1
console.warn 'The following did not have users:', nousers
@updateProgress Importer.ProgressStep.FINISHING
for channel in @channels.channels when channel.do_import and channel.is_archived
do (channel) =>
Meteor.runAsUser startedByUserId, () =>
Meteor.call 'archiveRoom', channel.rocketId
@updateProgress Importer.ProgressStep.DONE
timeTook = Date.now() - start
console.log "Import took #{timeTook} milliseconds."
# catch error
# @updateRecord { 'failed': true, 'error': error }
# console.error Importer.ProgressStep.ERROR
# throw new Error 'import-hipchat-error', error
return @getProgress()

@ -7,88 +7,88 @@ Importer.Slack = class Importer.Slack extends Importer.Base
prepare: (dataURI, sentContentType, fileName) =>
super(dataURI, sentContentType, fileName)
try
{image, contentType} = RocketChatFile.dataURIParse dataURI
zip = new @AdmZip(new Buffer(image, 'base64'))
zipEntries = zip.getEntries()
tempChannels = []
tempUsers = []
tempMessages = {}
for entry in zipEntries
do (entry) =>
if entry.entryName == 'channels.json'
@updateProgress Importer.ProgressStep.PREPARING_CHANNELS
tempChannels = JSON.parse entry.getData().toString()
else if entry.entryName == 'users.json'
@updateProgress Importer.ProgressStep.PREPARING_USERS
tempUsers = JSON.parse entry.getData().toString()
for user in tempUsers when user.is_bot
@bots[user.profile.bot_id] = user
else if not entry.isDirectory and entry.entryName.indexOf('/') > -1
item = entry.entryName.split('/') #random/2015-10-04.json
channelName = item[0] #random
msgGroupData = item[1].split('.')[0] #2015-10-04
if not tempMessages[channelName]
tempMessages[channelName] = {}
# Catch files which aren't valid JSON files, ignore them
try
tempMessages[channelName][msgGroupData] = JSON.parse entry.getData().toString()
catch
console.warn "#{entry.entryName} is not a valid JSON file! Unable to import it."
# Insert the users record, eventually this might have to be split into several ones as well
# if someone tries to import a several thousands users instance
usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers }
@users = @collection.findOne usersId
@updateRecord { 'count.users': tempUsers.length }
@addCountToTotal tempUsers.length
# Insert the channels records.
channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempChannels }
@channels = @collection.findOne channelsId
@updateRecord { 'count.channels': tempChannels.length }
@addCountToTotal tempChannels.length
# Insert the messages records
@updateProgress Importer.ProgressStep.PREPARING_MESSAGES
messagesCount = 0
for channel, messagesObj of tempMessages
do (channel, messagesObj) =>
if not @messages[channel]
@messages[channel] = {}
for date, msgs of messagesObj
messagesCount += msgs.length
@updateRecord { 'messagesstatus': "#{channel}/#{date}" }
if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize
for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs)
messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg }
@messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId
else
messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs }
@messages[channel][date] = @collection.findOne messagesId
@updateRecord { 'count.messages': messagesCount, 'messagesstatus': null }
@addCountToTotal messagesCount
if tempUsers.length is 0 or tempChannels.length is 0 or messagesCount is 0
@updateProgress Importer.ProgressStep.ERROR
return @getProgress()
selectionUsers = tempUsers.map (user) ->
return new Importer.SelectionUser user.id, user.name, user.profile.email, user.deleted, user.is_bot, !user.is_bot
selectionChannels = tempChannels.map (channel) ->
return new Importer.SelectionChannel channel.id, channel.name, channel.is_archived, true
# try
{image, contentType} = RocketChatFile.dataURIParse dataURI
zip = new @AdmZip(new Buffer(image, 'base64'))
zipEntries = zip.getEntries()
tempChannels = []
tempUsers = []
tempMessages = {}
for entry in zipEntries
do (entry) =>
if entry.entryName == 'channels.json'
@updateProgress Importer.ProgressStep.PREPARING_CHANNELS
tempChannels = JSON.parse entry.getData().toString()
else if entry.entryName == 'users.json'
@updateProgress Importer.ProgressStep.PREPARING_USERS
tempUsers = JSON.parse entry.getData().toString()
for user in tempUsers when user.is_bot
@bots[user.profile.bot_id] = user
else if not entry.isDirectory and entry.entryName.indexOf('/') > -1
item = entry.entryName.split('/') #random/2015-10-04.json
channelName = item[0] #random
msgGroupData = item[1].split('.')[0] #2015-10-04
if not tempMessages[channelName]
tempMessages[channelName] = {}
# Catch files which aren't valid JSON files, ignore them
try
tempMessages[channelName][msgGroupData] = JSON.parse entry.getData().toString()
catch
console.warn "#{entry.entryName} is not a valid JSON file! Unable to import it."
# Insert the users record, eventually this might have to be split into several ones as well
# if someone tries to import a several thousands users instance
usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers }
@users = @collection.findOne usersId
@updateRecord { 'count.users': tempUsers.length }
@addCountToTotal tempUsers.length
# Insert the channels records.
channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempChannels }
@channels = @collection.findOne channelsId
@updateRecord { 'count.channels': tempChannels.length }
@addCountToTotal tempChannels.length
# Insert the messages records
@updateProgress Importer.ProgressStep.PREPARING_MESSAGES
messagesCount = 0
for channel, messagesObj of tempMessages
do (channel, messagesObj) =>
if not @messages[channel]
@messages[channel] = {}
for date, msgs of messagesObj
messagesCount += msgs.length
@updateRecord { 'messagesstatus': "#{channel}/#{date}" }
if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize
for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs)
messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg }
@messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId
else
messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs }
@messages[channel][date] = @collection.findOne messagesId
@updateRecord { 'count.messages': messagesCount, 'messagesstatus': null }
@addCountToTotal messagesCount
if tempUsers.length is 0 or tempChannels.length is 0 or messagesCount is 0
@updateProgress Importer.ProgressStep.ERROR
return @getProgress()
selectionUsers = tempUsers.map (user) ->
return new Importer.SelectionUser user.id, user.name, user.profile.email, user.deleted, user.is_bot, !user.is_bot
selectionChannels = tempChannels.map (channel) ->
return new Importer.SelectionChannel channel.id, channel.name, channel.is_archived, true
@updateProgress Importer.ProgressStep.USER_SELECTION
return new Importer.Selection @name, selectionUsers, selectionChannels
catch error
@updateRecord { 'failed': true, 'error': error }
console.error Importer.ProgressStep.ERROR
throw new Error 'import-slack-error', error
@updateProgress Importer.ProgressStep.USER_SELECTION
return new Importer.Selection @name, selectionUsers, selectionChannels
# catch error
# @updateRecord { 'failed': true, 'error': error }
# console.error Importer.ProgressStep.ERROR
# throw new Error 'import-slack-error', error
startImport: (importSelection) =>
super(importSelection)
@ -106,183 +106,183 @@ Importer.Slack = class Importer.Slack extends Importer.Base
startedByUserId = Meteor.userId()
Meteor.defer =>
try
@updateProgress Importer.ProgressStep.IMPORTING_USERS
for user in @users.users when user.do_import
do (user) =>
Meteor.runAsUser startedByUserId, () =>
existantUser = RocketChat.models.Users.findOneByEmailAddress user.profile.email
if existantUser
user.rocketId = existantUser._id
@userTags.push
slack: "<@#{user.id}>"
slackLong: "<@#{user.id}|#{user.name}>"
rocket: "@#{existantUser.username}"
else
userId = Accounts.createUser { email: user.profile.email, password: Date.now() + user.name + user.profile.email.toUpperCase() }
Meteor.runAsUser userId, () =>
Meteor.call 'setUsername', user.name
Meteor.call 'joinDefaultChannels', true
url = null
if user.profile.image_original
url = user.profile.image_original
else if user.profile.image_512
url = user.profile.image_512
Meteor.call 'setAvatarFromService', url, null, 'url'
# Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600
if user.tz_offset
Meteor.call 'updateUserUtcOffset', user.tz_offset / 3600
if user.profile.real_name
RocketChat.models.Users.setName userId, user.profile.real_name
#Deleted users are 'inactive' users in Rocket.Chat
if user.deleted
Meteor.call 'setUserActiveStatus', userId, false
#TODO: Maybe send emails?
user.rocketId = userId
@userTags.push
slack: "<@#{user.id}>"
slackLong: "<@#{user.id}|#{user.name}>"
rocket: "@#{user.name}"
@addCountCompleted 1
@collection.update { _id: @users._id }, { $set: { 'users': @users.users }}
@updateProgress Importer.ProgressStep.IMPORTING_CHANNELS
for channel in @channels.channels when channel.do_import
do (channel) =>
Meteor.runAsUser startedByUserId, () =>
existantRoom = RocketChat.models.Rooms.findOneByName channel.name
if existantRoom or channel.is_general
if channel.is_general and channel.name isnt existantRoom?.name
Meteor.call 'saveRoomSettings', 'GENERAL', 'roomName', channel.name
channel.rocketId = if channel.is_general then 'GENERAL' else existantRoom._id
else
users = []
for member in channel.members when member isnt channel.creator
user = @getRocketUser member
if user?
users.push user.username
userId = ''
for user in @users.users when user.id is channel.creator
userId = user.rocketId
Meteor.runAsUser userId, () =>
returned = Meteor.call 'createChannel', channel.name, users
channel.rocketId = returned.rid
# @TODO implement model specific function
roomUpdate =
ts: new Date(channel.created * 1000)
if not _.isEmpty channel.topic?.value
roomUpdate.topic = channel.topic.value
lastSetTopic = channel.topic.last_set
if not _.isEmpty(channel.purpose?.value) and channel.purpose.last_set > lastSetTopic
roomUpdate.topic = channel.purpose.value
RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: roomUpdate }
@addCountCompleted 1
@collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }}
missedTypes = {}
ignoreTypes = { 'bot_add': true, 'file_comment': true, 'file_mention': true, 'channel_name': true }
@updateProgress Importer.ProgressStep.IMPORTING_MESSAGES
for channel, messagesObj of @messages
do (channel, messagesObj) =>
Meteor.runAsUser startedByUserId, () =>
slackChannel = @getSlackChannelFromName channel
if slackChannel?.do_import
room = RocketChat.models.Rooms.findOneById slackChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } }
for date, msgs of messagesObj
@updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" }
for message in msgs.messages
if message.type is 'message'
if message.subtype?
if message.subtype is 'channel_join'
if @getRocketUser(message.user)?
RocketChat.models.Messages.createUserJoinWithRoomIdAndUser room._id, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }
else if message.subtype is 'channel_leave'
if @getRocketUser(message.user)?
RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser room._id, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }
else if message.subtype is 'me_message'
RocketChat.sendMessage @getRocketUser(message.user), { msg: '_' + @convertSlackMessageToRocketChat(message.text) + '_', ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }, room
else if message.subtype is 'bot_message'
botUser = RocketChat.models.Users.findOneById 'rocket.cat', { fields: { username: 1 }}
botUsername = if @bots[message.bot_id] then @bots[message.bot_id]?.name else message.username
msgObj =
msg: if message.text then message.text else ''
ts: new Date(parseInt(message.ts.split('.')[0]) * 1000)
# try
@updateProgress Importer.ProgressStep.IMPORTING_USERS
for user in @users.users when user.do_import
do (user) =>
Meteor.runAsUser startedByUserId, () =>
existantUser = RocketChat.models.Users.findOneByEmailAddress user.profile.email
if existantUser
user.rocketId = existantUser._id
@userTags.push
slack: "<@#{user.id}>"
slackLong: "<@#{user.id}|#{user.name}>"
rocket: "@#{existantUser.username}"
else
userId = Accounts.createUser { email: user.profile.email, password: Date.now() + user.name + user.profile.email.toUpperCase() }
Meteor.runAsUser userId, () =>
Meteor.call 'setUsername', user.name
Meteor.call 'joinDefaultChannels', true
url = null
if user.profile.image_original
url = user.profile.image_original
else if user.profile.image_512
url = user.profile.image_512
Meteor.call 'setAvatarFromService', url, null, 'url'
# Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600
if user.tz_offset
Meteor.call 'updateUserUtcOffset', user.tz_offset / 3600
if user.profile.real_name
RocketChat.models.Users.setName userId, user.profile.real_name
#Deleted users are 'inactive' users in Rocket.Chat
if user.deleted
Meteor.call 'setUserActiveStatus', userId, false
#TODO: Maybe send emails?
user.rocketId = userId
@userTags.push
slack: "<@#{user.id}>"
slackLong: "<@#{user.id}|#{user.name}>"
rocket: "@#{user.name}"
@addCountCompleted 1
@collection.update { _id: @users._id }, { $set: { 'users': @users.users }}
@updateProgress Importer.ProgressStep.IMPORTING_CHANNELS
for channel in @channels.channels when channel.do_import
do (channel) =>
Meteor.runAsUser startedByUserId, () =>
existantRoom = RocketChat.models.Rooms.findOneByName channel.name
if existantRoom or channel.is_general
if channel.is_general and channel.name isnt existantRoom?.name
Meteor.call 'saveRoomSettings', 'GENERAL', 'roomName', channel.name
channel.rocketId = if channel.is_general then 'GENERAL' else existantRoom._id
else
users = []
for member in channel.members when member isnt channel.creator
user = @getRocketUser member
if user?
users.push user.username
userId = ''
for user in @users.users when user.id is channel.creator
userId = user.rocketId
Meteor.runAsUser userId, () =>
returned = Meteor.call 'createChannel', channel.name, users
channel.rocketId = returned.rid
# @TODO implement model specific function
roomUpdate =
ts: new Date(channel.created * 1000)
if not _.isEmpty channel.topic?.value
roomUpdate.topic = channel.topic.value
lastSetTopic = channel.topic.last_set
if not _.isEmpty(channel.purpose?.value) and channel.purpose.last_set > lastSetTopic
roomUpdate.topic = channel.purpose.value
RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: roomUpdate }
@addCountCompleted 1
@collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }}
missedTypes = {}
ignoreTypes = { 'bot_add': true, 'file_comment': true, 'file_mention': true, 'channel_name': true }
@updateProgress Importer.ProgressStep.IMPORTING_MESSAGES
for channel, messagesObj of @messages
do (channel, messagesObj) =>
Meteor.runAsUser startedByUserId, () =>
slackChannel = @getSlackChannelFromName channel
if slackChannel?.do_import
room = RocketChat.models.Rooms.findOneById slackChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } }
for date, msgs of messagesObj
@updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" }
for message in msgs.messages
if message.type is 'message'
if message.subtype?
if message.subtype is 'channel_join'
if @getRocketUser(message.user)?
RocketChat.models.Messages.createUserJoinWithRoomIdAndUser room._id, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }
else if message.subtype is 'channel_leave'
if @getRocketUser(message.user)?
RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser room._id, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }
else if message.subtype is 'me_message'
RocketChat.sendMessage @getRocketUser(message.user), { msg: '_' + @convertSlackMessageToRocketChat(message.text) + '_', ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }, room
else if message.subtype is 'bot_message'
botUser = RocketChat.models.Users.findOneById 'rocket.cat', { fields: { username: 1 }}
botUsername = if @bots[message.bot_id] then @bots[message.bot_id]?.name else message.username
msgObj =
msg: if message.text then message.text else ''
ts: new Date(parseInt(message.ts.split('.')[0]) * 1000)
rid: room._id
bot: true
attachments: message.attachments
username: if botUsername then botUsername else undefined
if message.edited?
msgObj.ets = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000)
if message.icons?
msgObj.emoji = message.icons.emoji
msgObj.msg = @convertSlackMessageToRocketChat(msgObj.msg)
RocketChat.sendMessage botUser, msgObj, room
else if message.subtype is 'channel_purpose'
RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', room._id, message.purpose, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }
else if message.subtype is 'channel_topic'
RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', room._id, message.topic, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }
else if message.subtype is 'pinned_item'
RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', room._id, '', @getRocketUser(message.user),
ts: new Date(parseInt(message.ts.split('.')[0]) * 1000)
attachments: [
"text" : @convertSlackMessageToRocketChat message.attachments[0].text
"author_name" : message.attachments[0].author_subname
"author_icon" : getAvatarUrlFromUsername(message.attachments[0].author_subname)
]
else if message.subtype is 'file_share'
if message.file?.url_private_download isnt undefined
details =
name: message.file.name
size: message.file.size
type: message.file.mimetype
rid: room._id
bot: true
attachments: message.attachments
username: if botUsername then botUsername else undefined
if message.edited?
msgObj.ets = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000)
if message.icons?
msgObj.emoji = message.icons.emoji
msgObj.msg = @convertSlackMessageToRocketChat(msgObj.msg)
RocketChat.sendMessage botUser, msgObj, room
else if message.subtype is 'channel_purpose'
RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', room._id, message.purpose, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }
else if message.subtype is 'channel_topic'
RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', room._id, message.topic, @getRocketUser(message.user), { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000) }
else if message.subtype is 'pinned_item'
RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', room._id, '', @getRocketUser(message.user),
ts: new Date(parseInt(message.ts.split('.')[0]) * 1000)
attachments: [
"text" : @convertSlackMessageToRocketChat message.attachments[0].text
"author_name" : message.attachments[0].author_subname
"author_icon" : getAvatarUrlFromUsername(message.attachments[0].author_subname)
]
else if message.subtype is 'file_share'
if message.file?.url_private_download isnt undefined
details =
name: message.file.name
size: message.file.size
type: message.file.mimetype
rid: room._id
@uploadFile details, message.file.url_private_download, @getRocketUser(message.user), room, new Date(parseInt(message.ts.split('.')[0]) * 1000)
else
if not missedTypes[message.subtype] and not ignoreTypes[message.subtype]
missedTypes[message.subtype] = message
@uploadFile details, message.file.url_private_download, @getRocketUser(message.user), room, new Date(parseInt(message.ts.split('.')[0]) * 1000)
else
user = @getRocketUser(message.user)
if user?
msgObj =
msg: @convertSlackMessageToRocketChat message.text
ts: new Date(parseInt(message.ts.split('.')[0]) * 1000)
rid: room._id
u:
_id: user._id
username: user.username
if message.edited?
msgObj.ets = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000)
RocketChat.sendMessage @getRocketUser(message.user), msgObj, room
@addCountCompleted 1
console.log missedTypes
@updateProgress Importer.ProgressStep.FINISHING
for channel in @channels.channels when channel.do_import and channel.is_archived
do (channel) =>
Meteor.runAsUser startedByUserId, () =>
Meteor.call 'archiveRoom', channel.rocketId
@updateProgress Importer.ProgressStep.DONE
timeTook = Date.now() - start
console.log "Import took #{timeTook} milliseconds."
catch error
@updateRecord { 'failed': true, 'error': error }
@updateProgress Importer.ProgressStep.ERROR
console.error Importer.ProgressStep.ERROR
throw new Error 'import-slack-error', error
if not missedTypes[message.subtype] and not ignoreTypes[message.subtype]
missedTypes[message.subtype] = message
else
user = @getRocketUser(message.user)
if user?
msgObj =
msg: @convertSlackMessageToRocketChat message.text
ts: new Date(parseInt(message.ts.split('.')[0]) * 1000)
rid: room._id
u:
_id: user._id
username: user.username
if message.edited?
msgObj.ets = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000)
RocketChat.sendMessage @getRocketUser(message.user), msgObj, room
@addCountCompleted 1
console.log missedTypes
@updateProgress Importer.ProgressStep.FINISHING
for channel in @channels.channels when channel.do_import and channel.is_archived
do (channel) =>
Meteor.runAsUser startedByUserId, () =>
Meteor.call 'archiveRoom', channel.rocketId
@updateProgress Importer.ProgressStep.DONE
timeTook = Date.now() - start
console.log "Import took #{timeTook} milliseconds."
# catch error
# @updateRecord { 'failed': true, 'error': error }
# @updateProgress Importer.ProgressStep.ERROR
# console.error Importer.ProgressStep.ERROR
# throw new Error 'import-slack-error', error
return @getProgress()

@ -13,4 +13,5 @@ RocketChat.settings.get 'Site_Url', (key, value) ->
process.env.MOBILE_ROOT_URL = value
process.env.MOBILE_DDP_URL = value
# WebAppInternals.generateBoilerplate()
if WebAppInternals?.generateBoilerplate
WebAppInternals.generateBoilerplate()

@ -80,24 +80,30 @@ Template.message.onCreated ->
@wasEdited = msg.editedAt? and not RocketChat.MessageTypes.isSystemMessage(msg)
@body = do ->
isSystemMessage = RocketChat.MessageTypes.isSystemMessage(msg)
messageType = RocketChat.MessageTypes.getType(msg)
if messageType?.render?
return messageType.render(msg)
msg = messageType.render(msg)
else if messageType?.template?
# render template
else if messageType?.message?
if messageType.data?(msg)?
return TAPi18n.__(messageType.message, messageType.data(msg))
msg = TAPi18n.__(messageType.message, messageType.data(msg))
else
return TAPi18n.__(messageType.message)
msg = TAPi18n.__(messageType.message)
else
if msg.u?.username is RocketChat.settings.get('Chatops_Username')
msg.html = msg.msg
message = RocketChat.callbacks.run 'renderMentions', msg
msg = RocketChat.callbacks.run 'renderMentions', msg
# console.log JSON.stringify message
return msg.html
msg = msg.html
else
msg = renderMessageBody msg
return renderMessageBody msg
if isSystemMessage
return RocketChat.Markdown msg
else
return msg
Template.message.onViewRendered = (context) ->
view = this

@ -14,7 +14,7 @@
{{/if}}
<i class="{{roomIcon}} status-{{userStatus}}"></i>
<span class="room-title">{{roomName}}</span>
<span class="room-topic">{{roomTopic}}</span>
<span class="room-topic">{{{RocketChatMarkdown roomTopic}}}</span>
</h2>
</header>
<div class="container-bars">

@ -4,10 +4,10 @@ Accounts.config accountsConfig
RocketChat.settings.get 'Accounts_AllowedDomainsList', (_id, value) ->
domainWhiteList = _.map value.split(','), (domain) -> domain.trim()
restrictCreationByEmailDomain = (email) ->
restrictCreationByEmailDomain = if domainWhiteList.length == 1 then domainWhiteList[0] else (email) ->
ret = false
for domain in domainWhiteList
if email.match(domain + '$')
if email.match('@' + RegExp.escape(domain) + '$')
ret = true
break;

Loading…
Cancel
Save