-
Notifications
You must be signed in to change notification settings - Fork 11.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Omnichannel): System messages in transcripts (#32752)
- Loading branch information
1 parent
0de8ee1
commit 03c8b06
Showing
24 changed files
with
829 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
'@rocket.chat/omnichannel-services': minor | ||
'@rocket.chat/pdf-worker': minor | ||
'@rocket.chat/core-services': minor | ||
'@rocket.chat/model-typings': minor | ||
'@rocket.chat/i18n': minor | ||
'@rocket.chat/meteor': minor | ||
--- | ||
|
||
Added system messages support for Omnichannel PDF transcripts and email transcripts. Currently these transcripts don't render system messages and is shown as an empty message in PDF/email. This PR adds this support for all valid livechat system messages. | ||
|
||
Also added a new setting under transcripts, to toggle the inclusion of system messages in email and PDF transcripts. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
'@rocket.chat/omnichannel-services': patch | ||
'@rocket.chat/core-services': patch | ||
'@rocket.chat/meteor': patch | ||
--- | ||
|
||
Reduced time on generation of PDF transcripts. Earlier Rocket.Chat was fetching the required translations everytime a PDF transcript was requested, this process was async and was being unnecessarily being performed on every pdf transcript request. This PR improves this and now the translations are loaded at the start and kept in memory to process further pdf transcripts requests. This reduces the time of asynchronously fetching translations again and again. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export default { | ||
preset: 'ts-jest', | ||
errorOnDeprecated: true, | ||
testEnvironment: 'jsdom', | ||
modulePathIgnorePatterns: ['<rootDir>/dist/'], | ||
moduleNameMapper: { | ||
'\\.css$': 'identity-obj-proxy', | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
ee/packages/omnichannel-services/src/OmnichannelTranscript.fixtures.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import type { MessageTypesValues } from '@rocket.chat/core-typings'; | ||
|
||
export const validFile = { name: 'screenshot.png', buffer: Buffer.from([1, 2, 3]) }; | ||
|
||
export const invalidFile = { name: 'audio.mp3', buffer: null }; | ||
|
||
export const messages = [ | ||
{ | ||
msg: 'Hello, how can I help you today?', | ||
ts: '2022-11-21T16:00:00.000Z', | ||
u: { | ||
_id: '123', | ||
name: 'Juanito De Ponce', | ||
username: 'juanito.ponce', | ||
}, | ||
}, | ||
{ | ||
msg: 'I am having trouble with my account.', | ||
ts: '2022-11-21T16:00:00.000Z', | ||
u: { | ||
_id: '321', | ||
name: 'Christian Castro', | ||
username: 'cristiano.castro', | ||
}, | ||
md: [ | ||
{ | ||
type: 'UNORDERED_LIST', | ||
value: [ | ||
{ type: 'LIST_ITEM', value: [{ type: 'PLAIN_TEXT', value: 'I am having trouble with my account;' }] }, | ||
{ | ||
type: 'LIST_ITEM', | ||
value: [ | ||
{ type: 'PLAIN_TEXT', value: 'I am having trouble with my password. ' }, | ||
{ type: 'EMOJI', value: undefined, unicode: '🙂' }, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
{ | ||
msg: 'Can you please provide your account email?', | ||
ts: '2022-11-21T16:00:00.000Z', | ||
u: { | ||
_id: '123', | ||
name: 'Juanito De Ponce', | ||
username: 'juanito.ponce', | ||
}, | ||
}, | ||
]; | ||
|
||
export const validSystemMessage = { | ||
ts: '2022-11-21T16:00:00.000Z', | ||
u: { | ||
_id: '123', | ||
name: 'Juanito De Ponce', | ||
username: 'juanito.ponce', | ||
}, | ||
t: 'livechat-started' as MessageTypesValues, | ||
}; | ||
|
||
export const invalidSystemMessage = { | ||
ts: '2022-11-21T16:00:00.000Z', | ||
u: { | ||
_id: '123', | ||
name: 'Juanito De Ponce', | ||
username: 'juanito.ponce', | ||
}, | ||
t: 'some-system-message' as MessageTypesValues, | ||
}; |
119 changes: 119 additions & 0 deletions
119
ee/packages/omnichannel-services/src/OmnichannelTranscript.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import '@testing-library/jest-dom'; | ||
import type { IMessage } from '@rocket.chat/core-typings'; | ||
import { Logger } from '@rocket.chat/logger'; | ||
|
||
import { OmnichannelTranscript } from './OmnichannelTranscript'; | ||
import { invalidSystemMessage, messages, validSystemMessage } from './OmnichannelTranscript.fixtures'; | ||
|
||
jest.mock('@rocket.chat/pdf-worker', () => ({ | ||
PdfWorker: jest.fn().mockImplementation(() => ({ | ||
renderToStream: jest.fn().mockResolvedValue(Buffer.from('')), | ||
isMimeTypeValid: jest.fn(() => true), | ||
})), | ||
})); | ||
|
||
jest.mock('@rocket.chat/core-services', () => ({ | ||
ServiceClass: class {}, | ||
Upload: { | ||
getFileBuffer: jest.fn().mockResolvedValue(Buffer.from('')), | ||
uploadFile: jest.fn().mockResolvedValue({ _id: 'fileId', name: 'fileName' }), | ||
sendFileMessage: jest.fn(), | ||
}, | ||
Message: { | ||
sendMessage: jest.fn(), | ||
}, | ||
Room: { | ||
createDirectMessage: jest.fn().mockResolvedValue({ rid: 'roomId' }), | ||
}, | ||
QueueWorker: { | ||
queueWork: jest.fn(), | ||
}, | ||
Translation: { | ||
translate: jest.fn().mockResolvedValue('translated message'), | ||
translateToServerLanguage: jest.fn().mockResolvedValue('translated server message'), | ||
translateMultipleToServerLanguage: jest.fn((keys) => keys.map((key: any) => ({ key, value: key }))), | ||
}, | ||
Settings: { | ||
get: jest.fn().mockResolvedValue(''), | ||
}, | ||
})); | ||
|
||
jest.mock('@rocket.chat/models', () => ({ | ||
LivechatRooms: { | ||
findOneById: jest.fn().mockResolvedValue({}), | ||
setTranscriptRequestedPdfById: jest.fn(), | ||
unsetTranscriptRequestedPdfById: jest.fn(), | ||
setPdfTranscriptFileIdById: jest.fn(), | ||
}, | ||
Messages: { | ||
findLivechatMessagesWithoutTypes: jest.fn().mockReturnValue({ | ||
toArray: jest.fn().mockResolvedValue([]), | ||
}), | ||
}, | ||
Uploads: { | ||
findOneById: jest.fn().mockResolvedValue({}), | ||
}, | ||
Users: { | ||
findOneById: jest.fn().mockResolvedValue({}), | ||
findOneAgentById: jest.fn().mockResolvedValue({}), | ||
}, | ||
LivechatVisitors: { | ||
findOneEnabledById: jest.fn().mockResolvedValue({}), | ||
}, | ||
})); | ||
|
||
jest.mock('@rocket.chat/tools', () => ({ | ||
guessTimezone: jest.fn().mockReturnValue('UTC'), | ||
guessTimezoneFromOffset: jest.fn().mockReturnValue('UTC'), | ||
streamToBuffer: jest.fn().mockResolvedValue(Buffer.from('')), | ||
})); | ||
|
||
describe('OmnichannelTranscript', () => { | ||
let omnichannelTranscript: OmnichannelTranscript; | ||
|
||
beforeEach(() => { | ||
omnichannelTranscript = new OmnichannelTranscript(Logger); | ||
}); | ||
|
||
it('should return default timezone', async () => { | ||
const timezone = await omnichannelTranscript.getTimezone(); | ||
expect(timezone).toBe('UTC'); | ||
}); | ||
|
||
it('should parse the messages', async () => { | ||
const parsedMessages = await omnichannelTranscript.getMessagesData(messages as unknown as IMessage[]); | ||
console.log(parsedMessages[0]); | ||
expect(parsedMessages).toBeDefined(); | ||
expect(parsedMessages).toHaveLength(3); | ||
expect(parsedMessages[0]).toHaveProperty('files'); | ||
expect(parsedMessages[0].files).toHaveLength(0); | ||
expect(parsedMessages[0]).toHaveProperty('quotes'); | ||
expect(parsedMessages[0].quotes).toHaveLength(0); | ||
}); | ||
|
||
it('should parse system message', async () => { | ||
const parsedMessages = await omnichannelTranscript.getMessagesData([...messages, validSystemMessage] as unknown as IMessage[]); | ||
const systemMessage = parsedMessages[3]; | ||
expect(parsedMessages).toBeDefined(); | ||
expect(parsedMessages).toHaveLength(4); | ||
expect(systemMessage).toHaveProperty('t'); | ||
expect(systemMessage.t).toBe('livechat-started'); | ||
expect(systemMessage).toHaveProperty('msg'); | ||
expect(systemMessage.msg).toBe('Chat_started'); | ||
expect(systemMessage).toHaveProperty('files'); | ||
expect(systemMessage.files).toHaveLength(0); | ||
expect(systemMessage).toHaveProperty('quotes'); | ||
expect(systemMessage.quotes).toHaveLength(0); | ||
}); | ||
|
||
it('should parse an invalid system message', async () => { | ||
const parsedMessages = await omnichannelTranscript.getMessagesData([...messages, invalidSystemMessage] as unknown as IMessage[]); | ||
const systemMessage = parsedMessages[3]; | ||
console.log(parsedMessages[3]); | ||
expect(parsedMessages).toBeDefined(); | ||
expect(parsedMessages).toHaveLength(4); | ||
expect(systemMessage).toHaveProperty('t'); | ||
expect(systemMessage.t).toBe('some-system-message'); | ||
expect(systemMessage.msg).toBeUndefined(); | ||
}); | ||
}); |
Oops, something went wrong.