Skip to content

Commit

Permalink
feat(Omnichannel): Attachments in Email Transcripts (#32777)
Browse files Browse the repository at this point in the history
  • Loading branch information
yash-rajpal authored and debdutdeb committed Jul 29, 2024
1 parent 2adf7aa commit deaeda5
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/weak-taxis-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': minor
---

Added handling of attachments in Omnichannel email transcripts. Earlier attachments were being skipped and were being shown as empty space, now it should render the image attachments and should show relevant error message for unsupported attachments.
65 changes: 61 additions & 4 deletions apps/meteor/app/livechat/server/lib/LivechatTyped.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import type {
LivechatDepartmentDTO,
OmnichannelSourceType,
} from '@rocket.chat/core-typings';
import { ILivechatAgentStatus, UserStatus, isOmnichannelRoom } from '@rocket.chat/core-typings';
import { ILivechatAgentStatus, UserStatus, isFileAttachment, isFileImageAttachment, isOmnichannelRoom } from '@rocket.chat/core-typings';
import colors from '@rocket.chat/fuselage-tokens/colors.json';
import { Logger, type MainLogger } from '@rocket.chat/logger';
import {
LivechatDepartment,
Expand All @@ -37,6 +38,7 @@ import {
ReadReceipts,
Rooms,
LivechatCustomField,
Uploads,
} from '@rocket.chat/models';
import { serverFetch as fetch } from '@rocket.chat/server-fetch';
import { Match, check } from 'meteor/check';
Expand Down Expand Up @@ -613,6 +615,7 @@ class LivechatClass {
'livechat-started',
'livechat_video_call',
];
const acceptableImageMimeTypes = ['image/jpeg', 'image/png', 'image/jpg'];
const messages = await Messages.findVisibleByRoomIdNotContainingTypesBeforeTs(
rid,
ignoredMessageTypes,
Expand All @@ -623,21 +626,75 @@ class LivechatClass {
);

let html = '<div> <hr>';
await messages.forEach((message) => {
const InvalidFileMessage = `<div style="background-color: ${colors.n100}; text-align: center; border-color: ${
colors.n250
}; border-width: 1px; border-style: solid; border-radius: 4px; padding-top: 8px; padding-bottom: 8px; margin-top: 4px;">${i18n.t(
'This_attachment_is_not_supported',
{ lng: userLanguage },
)}</div>`;

for await (const message of messages) {
let author;
if (message.u._id === visitor._id) {
author = i18n.t('You', { lng: userLanguage });
} else {
author = showAgentInfo ? message.u.name || message.u.username : i18n.t('Agent', { lng: userLanguage });
}

let messageContent = message.msg;
let filesHTML = '';

if (message.attachments && message.attachments?.length > 0) {
messageContent = message.attachments[0].description || '';

for await (const attachment of message.attachments) {
if (!isFileAttachment(attachment)) {
// ignore other types of attachments
continue;
}

if (!isFileImageAttachment(attachment)) {
filesHTML += `<div>${attachment.title || ''}${InvalidFileMessage}</div>`;
continue;
}

if (!attachment.image_type || !acceptableImageMimeTypes.includes(attachment.image_type)) {
filesHTML += `<div>${attachment.title || ''}${InvalidFileMessage}</div>`;
continue;
}

// Image attachment can be rendered in email body
const file = message.files?.find((file) => file.name === attachment.title);

if (!file) {
filesHTML += `<div>${attachment.title || ''}${InvalidFileMessage}</div>`;
continue;
}

const uploadedFile = await Uploads.findOneById(file._id);

if (!uploadedFile) {
filesHTML += `<div>${file.name}${InvalidFileMessage}</div>`;
continue;
}

const uploadedFileBuffer = await FileUpload.getBuffer(uploadedFile);
filesHTML += `<div styles="color: ${colors.n700}; margin-top: 4px; flex-direction: "column";"><p>${file.name}</p><img src="data:${
attachment.image_type
};base64,${uploadedFileBuffer.toString(
'base64',
)}" style="width: 400px; max-height: 240px; object-fit: contain; object-position: 0;"/></div>`;
}
}

const datetime = moment.tz(message.ts, timezone).locale(userLanguage).format('LLL');
const singleMessage = `
<p><strong>${author}</strong> <em>${datetime}</em></p>
<p>${message.msg}</p>
<p>${messageContent}</p>
<p>${filesHTML}</p>
`;
html += singleMessage;
});
}

html = `${html}</div>`;

Expand Down

0 comments on commit deaeda5

Please sign in to comment.