The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/packages/rocketchat-importer-hipchat/server.js

347 lines
12 KiB

/* globals Importer */
import moment from 'moment';
import 'moment-timezone';
Importer.HipChat = Importer.HipChat = (function() {
class HipChat extends Importer.Base {
constructor(name, descriptionI18N, mimeType) {
super(name, descriptionI18N, mimeType);
this.logger.debug('Constructed a new Slack Importer.');
this.userTags = [];
}
prepare(dataURI, sentContentType, fileName) {
super.prepare(dataURI, sentContentType, fileName);
const image = RocketChatFile.dataURIParse(dataURI).image;
// const contentType = ref.contentType;
const zip = new this.AdmZip(new Buffer(image, 'base64'));
const zipEntries = zip.getEntries();
const tempRooms = [];
let tempUsers = [];
const tempMessages = {};
zipEntries.forEach(entry => {
if (entry.entryName.indexOf('__MACOSX') > -1) {
this.logger.debug(`Ignoring the file: ${ entry.entryName }`);
}
if (entry.isDirectory) {
return;
}
if (entry.entryName.indexOf(Importer.HipChat.RoomPrefix) > -1) {
let roomName = entry.entryName.split(Importer.HipChat.RoomPrefix)[1];
if (roomName === 'list.json') {
this.updateProgress(Importer.ProgressStep.PREPARING_CHANNELS);
const tempRooms = JSON.parse(entry.getData().toString()).rooms;
tempRooms.forEach(room => {
room.name = _.slugify(room.name);
});
} else if (roomName.indexOf('/') > -1) {
const item = roomName.split('/');
roomName = _.slugify(item[0]);
const msgGroupData = item[1].split('.')[0];
if (!tempMessages[roomName]) {
tempMessages[roomName] = {};
}
try {
return tempMessages[roomName][msgGroupData] = JSON.parse(entry.getData().toString());
} catch (error) {
return this.logger.warn(`${ entry.entryName } is not a valid JSON file! Unable to import it.`);
}
}
} else if (entry.entryName.indexOf(Importer.HipChat.UsersPrefix) > -1) {
const usersName = entry.entryName.split(Importer.HipChat.UsersPrefix)[1];
if (usersName === 'list.json') {
this.updateProgress(Importer.ProgressStep.PREPARING_USERS);
return tempUsers = JSON.parse(entry.getData().toString()).users;
} else {
return this.logger.warn(`Unexpected file in the ${ this.name } import: ${ entry.entryName }`);
}
}
});
const usersId = this.collection.insert({
'import': this.importRecord._id,
'importer': this.name,
'type': 'users',
'users': tempUsers
});
this.users = this.collection.findOne(usersId);
this.updateRecord({
'count.users': tempUsers.length
});
this.addCountToTotal(tempUsers.length);
const channelsId = this.collection.insert({
'import': this.importRecord._id,
'importer': this.name,
'type': 'channels',
'channels': tempRooms
});
this.channels = this.collection.findOne(channelsId);
this.updateRecord({
'count.channels': tempRooms.length
});
this.addCountToTotal(tempRooms.length);
this.updateProgress(Importer.ProgressStep.PREPARING_MESSAGES);
let messagesCount = 0;
Object.keys(tempMessages).forEach(channel => {
const messagesObj = tempMessages[channel];
this.messages[channel] = this.messages[channel] || {};
Object.keys(messagesObj).forEach(date => {
const msgs = messagesObj[date];
messagesCount += msgs.length;
this.updateRecord({
'messagesstatus': `${ channel }/${ date }`
});
if (Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize) {
Importer.Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
const messagesId = this.collection.insert({
'import': this.importRecord._id,
'importer': this.name,
'type': 'messages',
'name': `${ channel }/${ date }.${ i }`,
'messages': splitMsg
});
this.messages[channel][`${ date }.${ i }`] = this.collection.findOne(messagesId);
});
} else {
const messagesId = this.collection.insert({
'import': this.importRecord._id,
'importer': this.name,
'type': 'messages',
'name': `${ channel }/${ date }`,
'messages': msgs
});
this.messages[channel][date] = this.collection.findOne(messagesId);
}
});
});
this.updateRecord({
'count.messages': messagesCount,
'messagesstatus': null
});
this.addCountToTotal(messagesCount);
if (tempUsers.length === 0 || tempRooms.length === 0 || messagesCount === 0) {
this.logger.warn(`The loaded users count ${ tempUsers.length }, the loaded channels ${ tempRooms.length }, and the loaded messages ${ messagesCount }`);
this.updateProgress(Importer.ProgressStep.ERROR);
return this.getProgress();
}
const selectionUsers = tempUsers.map(function(user) {
return new Importer.SelectionUser(user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot);
});
const selectionChannels = tempRooms.map(function(room) {
return new Importer.SelectionChannel(room.room_id, room.name, room.is_archived, true, false);
});
const selectionMessages = this.importRecord.count.messages;
this.updateProgress(Importer.ProgressStep.USER_SELECTION);
return new Importer.Selection(this.name, selectionUsers, selectionChannels, selectionMessages);
}
startImport(importSelection) {
super.startImport(importSelection);
const start = Date.now();
importSelection.users.forEach(user => {
this.users.users.forEach(u => {
if (u.user_id === user.user_id) {
u.do_import = user.do_import;
}
});
});
this.collection.update({_id: this.users._id}, { $set: { 'users': this.users.users } });
importSelection.channels.forEach(channel =>
this.channels.channels.forEach(c => c.room_id === channel.channel_id && (c.do_import = channel.do_import))
);
this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
const startedByUserId = Meteor.userId();
Meteor.defer(() => {
this.updateProgress(Importer.ProgressStep.IMPORTING_USERS);
this.users.users.forEach(user => {
if (!user.do_import) {
return;
}
Meteor.runAsUser(startedByUserId, () => {
const existantUser = RocketChat.models.Users.findOneByEmailAddress(user.email);
if (existantUser) {
user.rocketId = existantUser._id;
this.userTags.push({
hipchat: `@${ user.mention_name }`,
rocket: `@${ existantUser.username }`
});
} else {
const userId = Accounts.createUser({
email: user.email,
password: Date.now() + user.name + user.email.toUpperCase()
});
user.rocketId = userId;
this.userTags.push({
hipchat: `@${ user.mention_name }`,
rocket: `@${ user.mention_name }`
});
Meteor.runAsUser(userId, () => {
Meteor.call('setUsername', user.mention_name, {
joinDefaultChannelsSilenced: true
});
Meteor.call('setAvatarFromService', user.photo_url, undefined, 'url');
return Meteor.call('userSetUtcOffset', parseInt(moment().tz(user.timezone).format('Z').toString().split(':')[0]));
});
if (user.name != null) {
RocketChat.models.Users.setName(userId, user.name);
}
if (user.is_deleted) {
Meteor.call('setUserActiveStatus', userId, false);
}
}
return this.addCountCompleted(1);
});
});
this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
this.updateProgress(Importer.ProgressStep.IMPORTING_CHANNELS);
this.channels.channels.forEach(channel => {
if (!channel.do_import) {
return;
}
Meteor.runAsUser(startedByUserId, () => {
channel.name = channel.name.replace(/ /g, '');
const existantRoom = RocketChat.models.Rooms.findOneByName(channel.name);
if (existantRoom) {
channel.rocketId = existantRoom._id;
} else {
let userId = '';
this.users.users.forEach(user => {
if (user.user_id === channel.owner_user_id) {
userId = user.rocketId;
}
});
if (userId === '') {
this.logger.warn(`Failed to find the channel creator for ${ channel.name }, setting it to the current running user.`);
userId = startedByUserId;
}
Meteor.runAsUser(userId, () => {
const returned = Meteor.call('createChannel', channel.name, []);
return channel.rocketId = returned.rid;
});
RocketChat.models.Rooms.update({
_id: channel.rocketId
}, {
$set: {
'ts': new Date(channel.created * 1000)
}
});
}
return this.addCountCompleted(1);
});
});
this.collection.update({
_id: this.channels._id
}, {
$set: {
'channels': this.channels.channels
}
});
this.updateProgress(Importer.ProgressStep.IMPORTING_MESSAGES);
const nousers = {};
Object.keys(this.messages).forEach(channel => {
const messagesObj = this.messages[channel];
Meteor.runAsUser(startedByUserId, () => {
const hipchatChannel = this.getHipChatChannelFromName(channel);
if (hipchatChannel != null ? hipchatChannel.do_import : undefined) {
const room = RocketChat.models.Rooms.findOneById(hipchatChannel.rocketId, {
fields: {
usernames: 1,
t: 1,
name: 1
}
});
Object.keys(messagesObj).forEach(date => {
const msgs = messagesObj[date];
this.updateRecord({
'messagesstatus': `${ channel }/${ date }.${ msgs.messages.length }`
});
msgs.messages.forEach(message => {
if (message.from != null) {
const user = this.getRocketUser(message.from.user_id);
if (user != null) {
const msgObj = {
msg: this.convertHipChatMessageToRocketChat(message.message),
ts: new Date(message.date),
u: {
_id: user._id,
username: user.username
}
};
RocketChat.sendMessage(user, msgObj, room, true);
} else if (!nousers[message.from.user_id]) {
nousers[message.from.user_id] = message.from;
}
} else if (!_.isArray(message)) {
console.warn('Please report the following:', message);
}
this.addCountCompleted(1);
});
});
}
});
});
this.logger.warn('The following did not have users:', nousers);
this.updateProgress(Importer.ProgressStep.FINISHING);
this.channels.channels.forEach(channel => {
if (channel.do_import && channel.is_archived) {
Meteor.runAsUser(startedByUserId, () => {
return Meteor.call('archiveRoom', channel.rocketId);
});
}
});
this.updateProgress(Importer.ProgressStep.DONE);
const timeTook = Date.now() - start;
return this.logger.log(`Import took ${ timeTook } milliseconds.`);
});
return this.getProgress();
}
getHipChatChannelFromName(channelName) {
return this.channels.channels.find(channel => channel.name === channelName);
}
getRocketUser(hipchatId) {
const user = this.users.users.find(user => user.user_id === hipchatId);
return user ? RocketChat.models.Users.findOneById(user.rocketId, {
fields: {
username: 1,
name: 1
}
}) : undefined;
}
convertHipChatMessageToRocketChat(message) {
if (message != null) {
this.userTags.forEach(userReplace => {
message = message.replace(userReplace.hipchat, userReplace.rocket);
});
} else {
message = '';
}
return message;
}
getSelection() {
const selectionUsers = this.users.users.map(function(user) {
return new Importer.SelectionUser(user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot);
});
const selectionChannels = this.channels.channels.map(function(room) {
return new Importer.SelectionChannel(room.room_id, room.name, room.is_archived, true, false);
});
const selectionMessages = this.importRecord.count.messages;
return new Importer.Selection(this.name, selectionUsers, selectionChannels, selectionMessages);
}
}
HipChat.RoomPrefix = 'hipchat_export/rooms/';
HipChat.UsersPrefix = 'hipchat_export/users/';
return HipChat;
}());