diff --git a/.changeset/hip-mugs-promise.md b/.changeset/hip-mugs-promise.md new file mode 100644 index 000000000000..7100fec026e3 --- /dev/null +++ b/.changeset/hip-mugs-promise.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +improve: System messages for omni-visitor abandonment feature diff --git a/apps/meteor/ee/app/livechat-enterprise/server/lib/VisitorInactivityMonitor.ts b/apps/meteor/ee/app/livechat-enterprise/server/lib/VisitorInactivityMonitor.ts index 845b52be2d16..e4650fc21f3d 100644 --- a/apps/meteor/ee/app/livechat-enterprise/server/lib/VisitorInactivityMonitor.ts +++ b/apps/meteor/ee/app/livechat-enterprise/server/lib/VisitorInactivityMonitor.ts @@ -1,4 +1,4 @@ -import type { IOmnichannelRoom, IUser } from '@rocket.chat/core-typings'; +import type { ILivechatVisitor, IOmnichannelRoom, IUser } from '@rocket.chat/core-typings'; import { LivechatVisitors, LivechatRooms, LivechatDepartment, Users } from '@rocket.chat/models'; import { OmnichannelEEService } from '@rocket.chat/core-services'; import { cronJobs } from '@rocket.chat/cron'; @@ -70,14 +70,13 @@ export class VisitorInactivityMonitor { _initializeMessageCache() { this.messageCache.clear(); - this.messageCache.set('default', settings.get('Livechat_abandoned_rooms_closed_custom_message') || i18n.t('Closed_automatically')); } async _getDepartmentAbandonedCustomMessage(departmentId: string) { this.logger.debug(`Getting department abandoned custom message for department ${departmentId}`); - if (this.messageCache.has('departmentId')) { + if (this.messageCache.has(departmentId)) { this.logger.debug(`Using cached department abandoned custom message for department ${departmentId}`); - return this.messageCache.get('departmentId'); + return this.messageCache.get(departmentId); } const department = await LivechatDepartment.findOneById(departmentId); if (!department) { @@ -91,7 +90,7 @@ export class VisitorInactivityMonitor { async closeRooms(room: IOmnichannelRoom) { this.logger.debug(`Closing room ${room._id}`); - let comment = this.messageCache.get('default'); + let comment = await this.getDefaultAbandonedCustomMessage('close', room.v._id); if (room.departmentId) { comment = (await this._getDepartmentAbandonedCustomMessage(room.departmentId)) || comment; } @@ -105,22 +104,8 @@ export class VisitorInactivityMonitor { async placeRoomOnHold(room: IOmnichannelRoom) { this.logger.debug(`Placing room ${room._id} on hold`); - const timeout = settings.get('Livechat_visitor_inactivity_timeout'); - const { v: { _id: visitorId } = {} } = room; - if (!visitorId) { - this.logger.debug(`Room ${room._id} does not have a visitor`); - throw new Error('error-invalid_visitor'); - } - - const visitor = await LivechatVisitors.findOneById(visitorId); - if (!visitor) { - this.logger.debug(`Room ${room._id} does not have a visitor`); - throw new Error('error-invalid_visitor'); - } - - const guest = visitor.name || visitor.username; - const comment = i18n.t('Omnichannel_On_Hold_due_to_inactivity', { guest, timeout }); + const comment = await this.getDefaultAbandonedCustomMessage('on-hold', room.v._id); const result = await Promise.allSettled([ OmnichannelEEService.placeRoomOnHold(room, comment, this.user), @@ -170,4 +155,39 @@ export class VisitorInactivityMonitor { this._initializeMessageCache(); } + + private async getDefaultAbandonedCustomMessage(abandonmentAction: 'close' | 'on-hold', visitorId: string) { + const visitor = await LivechatVisitors.findOneById>(visitorId, { + projection: { + name: 1, + username: 1, + }, + }); + if (!visitor) { + this.logger.error({ + msg: 'Error getting default abandoned custom message: visitor not found', + visitorId, + }); + throw new Error('error-invalid_visitor'); + } + + const timeout = settings.get('Livechat_visitor_inactivity_timeout'); + + const guest = visitor.name || visitor.username; + + if (abandonmentAction === 'on-hold') { + return i18n.t('Omnichannel_On_Hold_due_to_inactivity', { + guest, + timeout, + }); + } + + return ( + settings.get('Livechat_abandoned_rooms_closed_custom_message') || + i18n.t('Omnichannel_chat_closed_due_to_inactivity', { + guest, + timeout, + }) + ); + } } diff --git a/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json index 6fe395013797..9f313e58c564 100644 --- a/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json @@ -3083,6 +3083,7 @@ "Livechat_offline": "Omnichannel offline", "Livechat_offline_message_sent": "Livechat offline message sent", "Livechat_OfflineMessageToChannel_enabled": "Send Livechat offline messages to a channel", + "Omnichannel_chat_closed_due_to_inactivity": "The chat was automatically closed because we haven't received any reply from {{guest}} in {{timeout}} seconds", "Omnichannel_on_hold_chat_resumed": "On Hold Chat Resumed: {{comment}}", "Omnichannel_on_hold_chat_automatically": "The chat was automatically resumed from On Hold upon receiving a new message from {{guest}}", "Omnichannel_on_hold_chat_resumed_manually": "The chat was manually resumed from On Hold by {{user}}", @@ -5947,4 +5948,4 @@ "Uninstall_grandfathered_app": "Uninstall {{appName}}?", "App_will_lose_grandfathered_status": "**This {{context}} app will lose its grandfathered status.** \n \nWorkspaces on Community Edition can have up to {{limit}} {{context}} apps enabled. Grandfathered apps count towards the limit but the limit is not applied to them.", "Theme_Appearence": "Theme Appearence" -} \ No newline at end of file +}