Merge pull request #8966 from RocketChat/slack-importer-related-fixes
[FIX] Importers failing when usernames exists but cases don't match and improve the importer framework's performancepull/9003/merge
commit
2f05cf196f
@ -0,0 +1,4 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { CsvImporterInfo } from '../info'; |
||||
|
||||
Importers.add(new CsvImporterInfo()); |
@ -0,0 +1,10 @@ |
||||
import { ImporterInfo } from 'meteor/rocketchat:importer'; |
||||
|
||||
export class CsvImporterInfo extends ImporterInfo { |
||||
constructor() { |
||||
super('csv', 'CSV', 'application/zip', [{ |
||||
text: 'Importer_CSV_Information', |
||||
href: 'https://rocket.chat/docs/administrator-guides/import/csv/' |
||||
}]); |
||||
} |
||||
} |
@ -1,10 +0,0 @@ |
||||
/* globals Importer */ |
||||
|
||||
Importer.addImporter('csv', Importer.CSV, { |
||||
name: 'CSV', |
||||
warnings: [{ |
||||
text: 'Importer_CSV_Information', |
||||
href: 'https://rocket.chat/docs/administrator-guides/import/csv/' |
||||
}], |
||||
mimeType: 'application/zip' |
||||
}); |
@ -0,0 +1,5 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { CsvImporterInfo } from '../info'; |
||||
import { CsvImporter } from './importer'; |
||||
|
||||
Importers.add(new CsvImporterInfo(), CsvImporter); |
@ -0,0 +1,4 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { HipChatEnterpriseImporterInfo } from '../info'; |
||||
|
||||
Importers.add(new HipChatEnterpriseImporterInfo()); |
@ -0,0 +1,15 @@ |
||||
import { ImporterInfo } from 'meteor/rocketchat:importer'; |
||||
|
||||
export class HipChatEnterpriseImporterInfo extends ImporterInfo { |
||||
constructor() { |
||||
super('hipchatenterprise', 'HipChat Enterprise', 'application/gzip', [ |
||||
{ |
||||
text: 'Importer_HipChatEnterprise_Information', |
||||
href: 'https://rocket.chat/docs/administrator-guides/import/hipchat/enterprise/' |
||||
}, { |
||||
text: 'Importer_HipChatEnterprise_BetaWarning', |
||||
href: 'https://github.com/RocketChat/Rocket.Chat/issues/new' |
||||
} |
||||
]); |
||||
} |
||||
} |
@ -1,15 +0,0 @@ |
||||
/* globals Importer */ |
||||
|
||||
Importer.addImporter('hipchatenterprise', Importer.HipChatEnterprise, { |
||||
name: 'HipChat Enterprise', |
||||
warnings: [ |
||||
{ |
||||
text: 'Importer_HipChatEnterprise_Information', |
||||
href: 'https://rocket.chat/docs/administrator-guides/import/hipchat/enterprise/' |
||||
}, { |
||||
text: 'Importer_HipChatEnterprise_BetaWarning', |
||||
href: 'https://github.com/RocketChat/Rocket.Chat/issues/new' |
||||
} |
||||
], |
||||
mimeType: 'application/gzip' |
||||
}); |
@ -0,0 +1,5 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { HipChatEnterpriseImporterInfo } from '../info'; |
||||
import { HipChatEnterpriseImporter } from './importer'; |
||||
|
||||
Importers.add(new HipChatEnterpriseImporterInfo(), HipChatEnterpriseImporter); |
@ -0,0 +1,4 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { HipChatImporterInfo } from '../info'; |
||||
|
||||
Importers.add(new HipChatImporterInfo()); |
@ -0,0 +1,7 @@ |
||||
import { ImporterInfo } from 'meteor/rocketchat:importer'; |
||||
|
||||
export class HipChatImporterInfo extends ImporterInfo { |
||||
constructor() { |
||||
super('hipchat', 'HipChat', 'application/zip'); |
||||
} |
||||
} |
@ -1,6 +0,0 @@ |
||||
/* globals Importer */ |
||||
|
||||
Importer.addImporter('hipchat', Importer.HipChat, { |
||||
name: 'HipChat', |
||||
mimeType: 'application/zip' |
||||
}); |
@ -1,349 +0,0 @@ |
||||
/* globals Importer */ |
||||
import _ from 'underscore'; |
||||
import s from 'underscore.string'; |
||||
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 = s.slugify(room.name); |
||||
}); |
||||
} else if (roomName.indexOf('/') > -1) { |
||||
const item = roomName.split('/'); |
||||
roomName = s.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; |
||||
|
||||
}()); |
@ -0,0 +1,5 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { HipChatImporterInfo } from '../info'; |
||||
import { HipChatImporter } from './importer'; |
||||
|
||||
Importers.add(new HipChatImporterInfo(), HipChatImporter); |
@ -0,0 +1,347 @@ |
||||
import { |
||||
Base, |
||||
ProgressStep, |
||||
Selection, |
||||
SelectionChannel, |
||||
SelectionUser |
||||
} from 'meteor/rocketchat:importer'; |
||||
|
||||
import _ from 'underscore'; |
||||
import s from 'underscore.string'; |
||||
import moment from 'moment'; |
||||
|
||||
import 'moment-timezone'; |
||||
|
||||
export class HipChatImporter extends Base { |
||||
constructor(info) { |
||||
super(info); |
||||
|
||||
this.userTags = []; |
||||
this.roomPrefix = 'hipchat_export/rooms/'; |
||||
this.usersPrefix = 'hipchat_export/users/'; |
||||
} |
||||
|
||||
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(this.roomPrefix) > -1) { |
||||
let roomName = entry.entryName.split(this.roomPrefix)[1]; |
||||
if (roomName === 'list.json') { |
||||
this.updateProgress(ProgressStep.PREPARING_CHANNELS); |
||||
const tempRooms = JSON.parse(entry.getData().toString()).rooms; |
||||
tempRooms.forEach(room => { |
||||
room.name = s.slugify(room.name); |
||||
}); |
||||
} else if (roomName.indexOf('/') > -1) { |
||||
const item = roomName.split('/'); |
||||
roomName = s.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(this.usersPrefix) > -1) { |
||||
const usersName = entry.entryName.split(this.usersPrefix)[1]; |
||||
if (usersName === 'list.json') { |
||||
this.updateProgress(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(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 (Base.getBSONSize(msgs) > Base.getMaxBSONSize()) { |
||||
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(ProgressStep.ERROR); |
||||
return this.getProgress(); |
||||
} |
||||
const selectionUsers = tempUsers.map(function(user) { |
||||
return new SelectionUser(user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot); |
||||
}); |
||||
const selectionChannels = tempRooms.map(function(room) { |
||||
return new SelectionChannel(room.room_id, room.name, room.is_archived, true, false); |
||||
}); |
||||
const selectionMessages = this.importRecord.count.messages; |
||||
this.updateProgress(ProgressStep.USER_SELECTION); |
||||
return new 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(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(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(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(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(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 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 SelectionChannel(room.room_id, room.name, room.is_archived, true, false); |
||||
}); |
||||
return new Selection(this.name, selectionUsers, selectionChannels, this.importRecord.count.messages); |
||||
} |
||||
} |
@ -0,0 +1 @@ |
||||
node_modules |
@ -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. |
@ -0,0 +1,10 @@ |
||||
{ |
||||
"lockfileVersion": 1, |
||||
"dependencies": { |
||||
"csv-parse": { |
||||
"version": "1.2.0", |
||||
"resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-1.2.0.tgz", |
||||
"integrity": "sha1-BHtzhoq5qFdG6IX2N/ntD7ZFpCU=" |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,4 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { SlackUsersImporterInfo } from '../info'; |
||||
|
||||
Importers.add(new SlackUsersImporterInfo()); |
@ -0,0 +1,10 @@ |
||||
import { ImporterInfo } from 'meteor/rocketchat:importer'; |
||||
|
||||
export class SlackUsersImporterInfo extends ImporterInfo { |
||||
constructor() { |
||||
super('slack-users', 'Slack_Users', 'text/csv', [{ |
||||
text: 'Importer_Slack_Users_CSV_Information', |
||||
href: 'https://rocket.chat/docs/administrator-guides/import/slack/users' |
||||
}]); |
||||
} |
||||
} |
@ -0,0 +1,29 @@ |
||||
Package.describe({ |
||||
name: 'rocketchat:importer-slack-users', |
||||
version: '1.0.0', |
||||
summary: 'Importer for Slack\'s CSV User Export', |
||||
git: '' |
||||
}); |
||||
|
||||
Package.onUse(function(api) { |
||||
api.use([ |
||||
'ecmascript', |
||||
'rocketchat:lib', |
||||
'rocketchat:importer' |
||||
]); |
||||
|
||||
api.use('rocketchat:logger', 'server'); |
||||
|
||||
// Importer information to both server and client
|
||||
api.addFiles('info.js'); |
||||
|
||||
// Server files
|
||||
api.addFiles(['server/importer.js', 'server/adder.js'], 'server'); |
||||
|
||||
// Client files
|
||||
api.addFiles('client/adder.js', 'client'); |
||||
}); |
||||
|
||||
Npm.depends({ |
||||
'csv-parse': '1.2.0' |
||||
}); |
@ -0,0 +1,5 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { SlackUsersImporterInfo } from '../info'; |
||||
import { SlackUsersImporter } from './importer'; |
||||
|
||||
Importers.add(new SlackUsersImporterInfo(), SlackUsersImporter); |
@ -0,0 +1,135 @@ |
||||
import { |
||||
Base, |
||||
ProgressStep, |
||||
Selection, |
||||
SelectionUser |
||||
} from 'meteor/rocketchat:importer'; |
||||
|
||||
export class SlackUsersImporter extends Base { |
||||
constructor(info) { |
||||
super(info); |
||||
|
||||
this.csvParser = Npm.require('csv-parse/lib/sync'); |
||||
this.userMap = new Map(); |
||||
this.admins = []; //Array of ids of the users which are admins
|
||||
} |
||||
|
||||
prepare(dataURI, sentContentType, fileName) { |
||||
super.prepare(dataURI, sentContentType, fileName, true); |
||||
|
||||
super.updateProgress(ProgressStep.PREPARING_USERS); |
||||
const uriResult = RocketChatFile.dataURIParse(dataURI); |
||||
const buf = new Buffer(uriResult.image, 'base64'); |
||||
const parsed = this.csvParser(buf.toString()); |
||||
|
||||
parsed.forEach((user, index) => { |
||||
// Ignore the first column
|
||||
if (index === 0) { |
||||
return; |
||||
} |
||||
|
||||
const id = Random.id(); |
||||
const username = user[0]; |
||||
const email = user[1]; |
||||
let isBot = false; |
||||
let isDeleted = false; |
||||
|
||||
switch (user[2]) { |
||||
case 'Admin': |
||||
this.admins.push(id); |
||||
break; |
||||
case 'Bot': |
||||
isBot = true; |
||||
break; |
||||
case 'Deactivated': |
||||
isDeleted = true; |
||||
break; |
||||
} |
||||
|
||||
this.userMap.set(id, new SelectionUser(id, username, email, isDeleted, isBot, true)); |
||||
}); |
||||
|
||||
const userArray = Array.from(this.userMap.values()); |
||||
|
||||
const usersId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'users', 'users': userArray }); |
||||
this.users = this.collection.findOne(usersId); |
||||
super.updateRecord({ 'count.users': this.userMap.size }); |
||||
super.addCountToTotal(this.userMap.size); |
||||
|
||||
if (this.userMap.size === 0) { |
||||
this.logger.error('No users found in the import file.'); |
||||
super.updateProgress(ProgressStep.ERROR); |
||||
return super.getProgress(); |
||||
} |
||||
|
||||
super.updateProgress(ProgressStep.USER_SELECTION); |
||||
return new Selection(this.name, userArray, [], 0); |
||||
} |
||||
|
||||
startImport(importSelection) { |
||||
super.startImport(importSelection); |
||||
const started = Date.now(); |
||||
|
||||
for (const user of importSelection.users) { |
||||
const u = this.userMap.get(user.user_id); |
||||
u.do_import = user.do_import; |
||||
|
||||
this.userMap.set(user.user_id, u); |
||||
} |
||||
this.collection.update({ _id: this.users._id }, { $set: { 'users': Array.from(this.userMap.values()) }}); |
||||
|
||||
const startedByUserId = Meteor.userId(); |
||||
Meteor.defer(() => { |
||||
super.updateProgress(ProgressStep.IMPORTING_USERS); |
||||
|
||||
for (const u of this.users.users) { |
||||
if (!u.do_import) { |
||||
continue; |
||||
} |
||||
|
||||
Meteor.runAsUser(startedByUserId, () => { |
||||
const existantUser = RocketChat.models.Users.findOneByEmailAddress(u.email) || RocketChat.models.Users.findOneByUsername(u.username); |
||||
|
||||
let userId = existantUser._id; |
||||
if (existantUser) { |
||||
//since we have an existing user, let's try a few things
|
||||
u.rocketId = existantUser._id; |
||||
RocketChat.models.Users.update({ _id: u.rocketId }, { $addToSet: { importIds: u.id } }); |
||||
|
||||
RocketChat.models.Users.setEmail(existantUser._id, u.email); |
||||
RocketChat.models.Users.setEmailVerified(existantUser._id, u.email); |
||||
} else { |
||||
userId = Accounts.createUser({ username: u.username + Random.id(), password: Date.now() + u.name + u.email.toUpperCase() }); |
||||
|
||||
if (!userId) { |
||||
console.warn('An error happened while creating a user.'); |
||||
return; |
||||
} |
||||
|
||||
Meteor.runAsUser(userId, () => { |
||||
Meteor.call('setUsername', u.username, {joinDefaultChannelsSilenced: true}); |
||||
RocketChat.models.Users.setName(userId, u.name); |
||||
RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: u.id } }); |
||||
RocketChat.models.Users.setEmail(userId, u.email); |
||||
RocketChat.models.Users.setEmailVerified(userId, u.email); |
||||
u.rocketId = userId; |
||||
}); |
||||
} |
||||
|
||||
if (this.admins.includes(u.user_id)) { |
||||
Meteor.call('setAdminStatus', userId, true); |
||||
} |
||||
|
||||
super.addCountCompleted(1); |
||||
}); |
||||
} |
||||
|
||||
super.updateProgress(ProgressStep.FINISHING); |
||||
super.updateProgress(ProgressStep.DONE); |
||||
const timeTook = Date.now() - started; |
||||
this.logger.log(`Slack Users Import took ${ timeTook } milliseconds.`); |
||||
}); |
||||
|
||||
return super.getProgress(); |
||||
} |
||||
} |
@ -0,0 +1,4 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { SlackImporterInfo } from '../info'; |
||||
|
||||
Importers.add(new SlackImporterInfo()); |
@ -0,0 +1,7 @@ |
||||
import { ImporterInfo } from 'meteor/rocketchat:importer'; |
||||
|
||||
export class SlackImporterInfo extends ImporterInfo { |
||||
constructor() { |
||||
super('slack', 'Slack', 'application/zip'); |
||||
} |
||||
} |
@ -1,5 +0,0 @@ |
||||
/* globals Importer */ |
||||
Importer.addImporter('slack', Importer.Slack, { |
||||
name: 'Slack', |
||||
mimeType: 'application/zip' |
||||
}); |
@ -0,0 +1,5 @@ |
||||
import { Importers } from 'meteor/rocketchat:importer'; |
||||
import { SlackImporterInfo } from '../info'; |
||||
import { SlackImporter } from './importer'; |
||||
|
||||
Importers.add(new SlackImporterInfo(), SlackImporter); |
@ -0,0 +1,29 @@ |
||||
class ImporterWebsocketReceiverDef { |
||||
constructor() { |
||||
this.streamer = new Meteor.Streamer('importers'); |
||||
|
||||
this.callbacks = []; |
||||
this.streamer.on('progress', this.progressUpdated.bind(this)); |
||||
} |
||||
|
||||
progressUpdated(progress) { |
||||
this.callbacks.forEach((c) => c(progress)); |
||||
} |
||||
|
||||
registerCallback(callback) { |
||||
if (typeof callback !== 'function') { |
||||
throw new Error('Callback must be a function.'); |
||||
} |
||||
|
||||
this.callbacks.push(callback); |
||||
} |
||||
|
||||
unregisterCallback(callback) { |
||||
const i = this.callbacks.indexOf(callback); |
||||
if (i >= 0) { |
||||
this.callbacks.splice(i, 1); |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const ImporterWebsocketReceiver = new ImporterWebsocketReceiverDef(); |
@ -0,0 +1,11 @@ |
||||
import { Importers } from '../lib/Importers'; |
||||
import { ImporterInfo } from '../lib/ImporterInfo'; |
||||
import { ImporterWebsocketReceiver } from './ImporterWebsocketReceiver'; |
||||
import { ProgressStep } from '../lib/ImporterProgressStep'; |
||||
|
||||
export { |
||||
Importers, |
||||
ImporterInfo, |
||||
ImporterWebsocketReceiver, |
||||
ProgressStep |
||||
}; |
@ -0,0 +1,19 @@ |
||||
export class ImporterInfo { |
||||
/** |
||||
* Creates a new class which contains information about the importer. |
||||
* |
||||
* @param {string} key The unique key of this importer. |
||||
* @param {string} name The i18n name. |
||||
* @param {string} mimeType The type of file it expects. |
||||
* @param {{ href: string, text: string }[]} warnings An array of warning objects. `{ href, text }` |
||||
*/ |
||||
constructor(key, name = '', mimeType = '', warnings = []) { |
||||
this.key = key; |
||||
this.name = name; |
||||
this.mimeType = mimeType; |
||||
this.warnings = warnings; |
||||
|
||||
this.importer = undefined; |
||||
this.instance = undefined; |
||||
} |
||||
} |
@ -1,6 +1,5 @@ |
||||
/* globals Importer */ |
||||
// "ENUM" of the import step, the value is the translation string
|
||||
Importer.ProgressStep = Object.freeze({ |
||||
/** The progress step that an importer is at. */ |
||||
export const ProgressStep = Object.freeze({ |
||||
NEW: 'importer_new', |
||||
PREPARING_STARTED: 'importer_preparing_started', |
||||
PREPARING_USERS: 'importer_preparing_users', |
@ -0,0 +1,47 @@ |
||||
import { ImporterInfo } from './ImporterInfo'; |
||||
|
||||
/** Container class which holds all of the importer details. */ |
||||
class ImportersContainer { |
||||
constructor() { |
||||
this.importers = new Map(); |
||||
} |
||||
|
||||
/** |
||||
* Adds an importer to the import collection. Adding it more than once will |
||||
* overwrite the previous one. |
||||
* |
||||
* @param {ImporterInfo} info The information related to the importer. |
||||
* @param {*} importer The class for the importer, will be undefined on the client. |
||||
*/ |
||||
add(info, importer) { |
||||
if (!(info instanceof ImporterInfo)) { |
||||
throw new Error('The importer must be a valid ImporterInfo instance.'); |
||||
} |
||||
|
||||
info.importer = importer; |
||||
|
||||
this.importers.set(info.key, info); |
||||
|
||||
return this.importers.get(info.key); |
||||
} |
||||
|
||||
/** |
||||
* Gets the importer information that is stored. |
||||
* |
||||
* @param {string} key The key of the importer. |
||||
*/ |
||||
get(key) { |
||||
return this.importers.get(key); |
||||
} |
||||
|
||||
/** |
||||
* Gets all of the importers in array format. |
||||
* |
||||
* @returns {ImporterInfo[]} The array of importer information. |
||||
*/ |
||||
getAll() { |
||||
return Array.from(this.importers.values()); |
||||
} |
||||
} |
||||
|
||||
export const Importers = new ImportersContainer(); |
@ -1,3 +0,0 @@ |
||||
/* globals Importer */ |
||||
Importer = {}; |
||||
export default Importer; |
@ -1,13 +0,0 @@ |
||||
/* globals Importer */ |
||||
Importer.Importers = {}; |
||||
|
||||
Importer.addImporter = function(name, importer, options) { |
||||
if (Importer.Importers[name] == null) { |
||||
return Importer.Importers[name] = { |
||||
name: options.name, |
||||
importer, |
||||
mimeType: options.mimeType, |
||||
warnings: options.warnings |
||||
}; |
||||
} |
||||
}; |
@ -1,13 +1,16 @@ |
||||
/* globals Importer */ |
||||
// Class for all the progress of the importers to use.
|
||||
Importer.Progress = (Importer.Progress = class Progress { |
||||
// Constructs a new progress object.
|
||||
//
|
||||
// @param [String] name the name of the Importer
|
||||
//
|
||||
constructor(name) { |
||||
import { ProgressStep } from '../../lib/ImporterProgressStep'; |
||||
|
||||
export class Progress { |
||||
/** |
||||
* Creates a new progress container for the importer. |
||||
* |
||||
* @param {string} key The unique key of the importer. |
||||
* @param {string} name The name of the importer. |
||||
*/ |
||||
constructor(key, name) { |
||||
this.key = key; |
||||
this.name = name; |
||||
this.step = Importer.ProgressStep.NEW; |
||||
this.step = ProgressStep.NEW; |
||||
this.count = { completed: 0, total: 0 }; |
||||
} |
||||
}); |
||||
} |
||||
|
@ -1,17 +1,16 @@ |
||||
/* globals Importer */ |
||||
// Class for all the selection of users and channels for the importers
|
||||
Importer.Selection = (Importer.Selection = class Selection { |
||||
// Constructs a new importer selection object.
|
||||
//
|
||||
// @param [String] name the name of the Importer
|
||||
// @param [Array<Importer.User>] users the array of users
|
||||
// @param [Array<Importer.Channel>] channels the array of channels
|
||||
// @param [Integer] number of collected messages
|
||||
//
|
||||
export class Selection { |
||||
/** |
||||
* Constructs a new importer selection object. |
||||
* |
||||
* @param {string} name the name of the importer |
||||
* @param {SelectionUser[]} users the users which can be selected |
||||
* @param {SelectionChannel[]} channels the channels which can be selected |
||||
* @param {number} message_count the number of messages |
||||
*/ |
||||
constructor(name, users, channels, message_count) { |
||||
this.name = name; |
||||
this.users = users; |
||||
this.channels = channels; |
||||
this.message_count = message_count; |
||||
} |
||||
}); |
||||
} |
||||
|
@ -0,0 +1,19 @@ |
||||
class ImporterWebsocketDef { |
||||
constructor() { |
||||
this.streamer = new Meteor.Streamer('importers', { retransmit: false }); |
||||
this.streamer.allowRead('all'); |
||||
this.streamer.allowEmit('all'); |
||||
this.streamer.allowWrite('none'); |
||||
} |
||||
|
||||
/** |
||||
* Called when the progress is updated. |
||||
* |
||||
* @param {Progress} progress The progress of the import. |
||||
*/ |
||||
progressUpdated(progress) { |
||||
this.streamer.emit('progress', progress); |
||||
} |
||||
} |
||||
|
||||
export const ImporterWebsocket = new ImporterWebsocketDef(); |
@ -0,0 +1,25 @@ |
||||
import { Base } from './classes/ImporterBase'; |
||||
import { Imports } from './models/Imports'; |
||||
import { Importers } from '../lib/Importers'; |
||||
import { ImporterInfo } from '../lib/ImporterInfo'; |
||||
import { ImporterWebsocket } from './classes/ImporterWebsocket'; |
||||
import { Progress } from './classes/ImporterProgress'; |
||||
import { ProgressStep } from '../lib/ImporterProgressStep'; |
||||
import { RawImports } from './models/RawImports'; |
||||
import { Selection } from './classes/ImporterSelection'; |
||||
import { SelectionChannel } from './classes/ImporterSelectionChannel'; |
||||
import { SelectionUser } from './classes/ImporterSelectionUser'; |
||||
|
||||
export { |
||||
Base, |
||||
Imports, |
||||
Importers, |
||||
ImporterInfo, |
||||
ImporterWebsocket, |
||||
Progress, |
||||
ProgressStep, |
||||
RawImports, |
||||
Selection, |
||||
SelectionChannel, |
||||
SelectionUser |
||||
}; |
@ -1,6 +1,7 @@ |
||||
/* globals Importer */ |
||||
Importer.Imports = new (Importer.Imports = class Imports extends RocketChat.models._Base { |
||||
class ImportsModel extends RocketChat.models._Base { |
||||
constructor() { |
||||
super('import'); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
export const Imports = new ImportsModel(); |
||||
|
@ -1,6 +1,7 @@ |
||||
/* globals Importer */ |
||||
Importer.RawImports = new (Importer.RawImports = class RawImports extends RocketChat.models._Base { |
||||
class RawImportsModel extends RocketChat.models._Base { |
||||
constructor() { |
||||
super('raw_imports'); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
export const RawImports = new RawImportsModel(); |
||||
|
@ -1,9 +1,16 @@ |
||||
/* globals Importer */ |
||||
import { Imports } from '../models/Imports'; |
||||
import { RawImports } from '../models/RawImports'; |
||||
|
||||
Meteor.startup(function() { |
||||
// Make sure all imports are marked as invalid, data clean up since you can't
|
||||
// restart an import at the moment.
|
||||
Importer.Imports.update({ valid: { $ne: false } }, { $set: { valid: false } }, { multi: true }); |
||||
Imports.update({ valid: { $ne: false } }, { $set: { valid: false } }, { multi: true }); |
||||
|
||||
// Clean up all the raw import data, since you can't restart an import at the moment
|
||||
return Importer.Imports.find({ valid: { $ne: true }}).forEach(item => Importer.RawImports.remove({ 'import': item._id, 'importer': item.type })); |
||||
try { |
||||
RawImports.model.rawCollection().drop(); |
||||
} catch (e) { |
||||
console.log('errror', e); //TODO: Remove
|
||||
// ignored
|
||||
} |
||||
}); |
||||
|
Loading…
Reference in new issue