import path from 'path'; import moment from 'moment'; import { Random } from 'meteor/random'; import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; import mkdirp from 'mkdirp'; import * as Mailer from '../../app/mailer'; import { Messages, Users } from '../../app/models/server'; import { settings } from '../../app/settings/server'; import { Message } from '../../app/ui-utils/server'; import { exportRoomMessagesToFile, copyFile, getRoomData, makeZipFile, sendEmail, uploadZipFile, } from '../../app/user-data-download/server/cronProcessDownloads'; import { IUser } from '../../definition/IUser'; import { getMomentLocale } from './getMomentLocale'; type ExportEmail = { rid: string; toUsers: string[]; toEmails: string[]; subject: string; messages: string[]; language: string; } type ExportFile = { rid: string; dateFrom: Date; dateTo: Date; format: 'html' | 'json'; } type ExportInput = { type: 'email'; data: ExportEmail; } | { type: 'file'; data: ExportFile; }; type ISentViaEmail = { missing: string[]; }; export const sendViaEmail = (data: ExportEmail, user: IUser): ISentViaEmail => { const emails = data.toEmails.map((email) => email.trim()).filter(Boolean); const missing = [...data.toUsers].filter(Boolean); Users.findUsersByUsernames(data.toUsers, { fields: { username: 1, 'emails.address': 1 } }).forEach((user: IUser) => { const emailAddress = user.emails?.[0].address; if (!emailAddress) { return; } if (!Mailer.checkAddressFormat(emailAddress)) { throw new Error('error-invalid-email'); } const found = missing.indexOf(String(user.username)); if (found !== -1) { missing.splice(found, 1); } emails.push(emailAddress); }); const email = user.emails?.[0]?.address; const lang = data.language || user.language || 'en'; const localMoment = moment(); if (lang !== 'en') { const localeFn = getMomentLocale(lang); if (localeFn) { Function(localeFn).call({ moment }); localMoment.locale(lang); } } const html = Messages.findByRoomIdAndMessageIds(data.rid, data.messages, { sort: { ts: 1 }, }).fetch().map(function(message: any) { const dateTime = moment(message.ts).locale(lang).format('L LT'); return `

${ message.u.username } ${ dateTime }
${ Message.parse(message, data.language) }

`; }).join(''); Mailer.send({ to: emails, from: settings.get('From_Email'), replyTo: email, subject: data.subject, html, } as any); return { missing }; }; export const sendFile = async (data: ExportFile, user: IUser): Promise => { const exportType = data.format; const baseDir = `/tmp/exportFile-${ Random.id() }`; const exportPath = baseDir; const assetsPath = path.join(baseDir, 'assets'); mkdirp.sync(exportPath); mkdirp.sync(assetsPath); const roomData = getRoomData(data.rid); roomData.targetFile = `${ (data.format === 'json' && roomData.roomName) || roomData.roomId }.${ data.format }`; const fullFileList: any[] = []; const roomsToExport = [roomData]; const filter = !data.dateFrom && !data.dateTo ? {} : { ts: { ...data.dateFrom && { $gte: data.dateFrom }, ...data.dateTo && { $lte: data.dateTo }, }, }; const exportMessages = async (): Promise => { const { fileList } = await exportRoomMessagesToFile( exportPath, assetsPath, exportType, roomsToExport, user, filter, {}, false, ); fullFileList.push(...fileList); const [roomData] = roomsToExport; if (roomData.status !== 'completed') { await exportMessages(); } }; await exportMessages(); fullFileList.forEach((attachmentData: any) => { copyFile(attachmentData, assetsPath); }); const exportFile = `${ baseDir }-export.zip`; await makeZipFile(exportPath, exportFile); const file = await uploadZipFile(exportFile, user._id, exportType); const subject = TAPi18n.__('Channel_Export'); // eslint-disable-next-line @typescript-eslint/camelcase const body = TAPi18n.__('UserDataDownload_EmailBody', { download_link: file.url }); sendEmail(user, subject, body); }; export async function channelExport(data: ExportInput, user: IUser): Promise { if (data.type === 'email') { return sendViaEmail(data.data, user); } return sendFile(data.data, user); }