Skip to content

Commit 5dc7da9

Browse files
authored
Merge pull request RocketChat#33 from Shailesh351/sb_timeout_warnings
Add Customer Idle Timeout Support
2 parents e88236b + 0b01eed commit 5dc7da9

5 files changed

Lines changed: 139 additions & 6 deletions

File tree

config/Settings.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ export enum AppSetting {
1818
DialogflowWelcomeMessage = 'dialogflow_welcome_message',
1919
DialogflowChatClosedByVisitorEventName = 'dialogflow_chat_closed_by_visitor_event_name',
2020
DialogflowWelcomeIntentOnStart = 'dialogflow_welcome_intent_on_start',
21+
DialogflowEnableCustomerTimeout = 'dialogflow_enable_customer_timeout',
22+
DialogflowCustomerTimeoutTime = 'dialogflow_customer_timeout_time',
23+
DialogflowCustomerTimeoutWarningTime = 'dialogflow_customer_timeout_warning_time',
24+
DialogflowCustomerTimeoutWarningMessage = 'dialogflow_customer_timeout_warning_message',
2125
}
2226

2327
export enum DefaultMessage {
@@ -183,4 +187,40 @@ export const settings: Array<ISetting> = [
183187
i18nDescription: 'dialogflow_welcome_intent_on_start_description',
184188
required: true,
185189
},
190+
{
191+
id: AppSetting.DialogflowEnableCustomerTimeout,
192+
public: true,
193+
type: SettingType.BOOLEAN,
194+
packageValue: false,
195+
i18nLabel: 'dialogflow_enable_customer_timeout',
196+
i18nDescription: 'dialogflow_enable_customer_timeout_description',
197+
required: true,
198+
},
199+
{
200+
id: AppSetting.DialogflowCustomerTimeoutTime,
201+
public: true,
202+
type: SettingType.NUMBER,
203+
packageValue: 60,
204+
i18nLabel: 'dialogflow_customer_timeout_time',
205+
i18nDescription: 'dialogflow_customer_timeout_time_description',
206+
required: true,
207+
},
208+
{
209+
id: AppSetting.DialogflowCustomerTimeoutWarningTime,
210+
public: true,
211+
type: SettingType.NUMBER,
212+
packageValue: 40,
213+
i18nLabel: 'dialogflow_customer_timeout_warning_time',
214+
i18nDescription: 'dialogflow_customer_timeout_warning_time_description',
215+
required: true,
216+
},
217+
{
218+
id: AppSetting.DialogflowCustomerTimeoutWarningMessage,
219+
public: true,
220+
type: SettingType.STRING,
221+
packageValue: 'Are you still there? Please send a message within %t or this chat will time out.',
222+
i18nLabel: 'dialogflow_customer_timeout_warning_message',
223+
i18nDescription: 'dialogflow_customer_timeout_warning_message_description',
224+
required: true,
225+
},
186226
];

enum/Dialogflow.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,5 @@ export enum DialogflowRequestType {
8787

8888
export enum Message {
8989
CLOSED_BY_VISITOR = 'Closed by visitor',
90+
CUSTOMER_IDEL_TIMEOUT = 'customer_idle_timeout'
9091
}

handler/PostMessageSentHandler.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ import { handlePayloadActions } from '../lib/payloadAction';
1212
import { closeChat, performHandover, updateRoomCustomFields } from '../lib/Room';
1313
import { getAppSettingValue } from '../lib/Settings';
1414
import { incFallbackIntentAndSendResponse, resetFallbackIntent } from '../lib/SynchronousHandover';
15+
import { handleTimeout } from '../lib/Timeout';
1516

1617
export class PostMessageSentHandler {
1718
constructor(private readonly app: IApp,
1819
private readonly message: ILivechatMessage,
1920
private readonly read: IRead,
2021
private readonly http: IHttp,
21-
private readonly persis: IPersistence,
22+
private readonly persistence: IPersistence,
2223
private readonly modify: IModify) { }
2324

2425
public async run() {
@@ -30,26 +31,34 @@ export class PostMessageSentHandler {
3031
const DialogflowBotUsername: string = await getAppSettingValue(this.read, AppSetting.DialogflowBotUsername);
3132

3233
if (text === Message.CLOSED_BY_VISITOR) {
33-
this.handleClosedByVisitor(rid);
34+
await this.handleClosedByVisitor(rid);
3435
}
3536

37+
if (text === Message.CUSTOMER_IDEL_TIMEOUT) {
38+
await this.handleClosedByVisitor(rid)
39+
await closeChat(this.modify, this.read, rid)
40+
return;
41+
}
42+
3643
if (!type || type !== RoomType.LIVE_CHAT) {
3744
return;
3845
}
3946

40-
if (!isOpen || !token || editedAt || !text) {
47+
if (!isOpen || editedAt || !text) {
4148
return;
4249
}
4350

4451
if (!servedBy || servedBy.username !== DialogflowBotUsername) {
4552
return;
4653
}
4754

48-
if (sender.username === DialogflowBotUsername) {
55+
if (!text || (text && text.trim().length === 0)) {
4956
return;
5057
}
5158

52-
if (!text || (text && text.trim().length === 0)) {
59+
await handleTimeout(this.app, this.message, this.read, this.http, this.persistence, this.modify);
60+
61+
if (sender.username === DialogflowBotUsername) {
5362
return;
5463
}
5564

i18n/en.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,13 @@
2828
"dialogflow_welcome_message": "Dialogflow Message to send on start",
2929
"dialogflow_welcome_message_description": "Custom welcome message to send to visitor",
3030
"dialogflow_welcome_intent_on_start": "Send Welcome Intent",
31-
"dialogflow_welcome_intent_on_start_description": "If enabled, then a welcome event will be sent when bot is assigned to any visitor"
31+
"dialogflow_welcome_intent_on_start_description": "If enabled, then a welcome event will be sent when bot is assigned to any visitor",
32+
"dialogflow_enable_customer_timeout":"Enable Customer Time-Out",
33+
"dialogflow_enable_customer_timeout_description":"Indicates whether chats are ended if the customer doesn’t respond within a specified period.",
34+
"dialogflow_customer_timeout_time":"Customer Time-Out Time (seconds)",
35+
"dialogflow_customer_timeout_time_description":"Sets the amount of time that a customer has to respond to an agent message before the session ends. The timer stops when the customer sends a message and starts again from 0 on the next agent's message.",
36+
"dialogflow_customer_timeout_warning_time":"Customer Time-Out Warning Time (seconds)",
37+
"dialogflow_customer_timeout_warning_time_description":"Sets the amount of time that a customer has to respond to an agent message before a warning appears and a timer begins a countdown. \nThe warning disappears (and the timer stops) each time the customer sends a message. \nThe warning disappears (and the timer resets to 0) each time the agent sends message. \nThe warning value must be shorter than the time-out value (we recommend at least 30 seconds).",
38+
"dialogflow_customer_timeout_warning_message":"Customer Time-Out Warning Message",
39+
"dialogflow_customer_timeout_warning_message_description":"Enter message to show to user as idle timeout warning. Use %t as placeholder for count down."
3240
}

lib/Timeout.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors';
2+
import { IApp } from '@rocket.chat/apps-engine/definition/IApp';
3+
import { IMessage } from '@rocket.chat/apps-engine/definition/messages';
4+
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';
5+
import { AppSetting } from '../config/Settings';
6+
import { getAppSettingValue } from '../lib/Settings';
7+
8+
export const handleTimeout = async (app: IApp, message: IMessage, read: IRead, http: IHttp, persistence: IPersistence, modify: IModify ) => {
9+
10+
if (message.room.type !== RoomType.LIVE_CHAT || (message.customFields && message.customFields.idleTimeoutConfig)) {
11+
return;
12+
}
13+
14+
const dialogflowBotUsername: string = (await getAppSettingValue(read, AppSetting.DialogflowBotUsername));
15+
const chasitorIdleTimeoutIsEnabled: string = (await getAppSettingValue(read, AppSetting.DialogflowEnableCustomerTimeout));
16+
17+
if (chasitorIdleTimeoutIsEnabled) {
18+
19+
/**
20+
* Sets the amount of time that a customer has to respond to an agent message before a warning appears and a timer begins a countdown.
21+
* The warning disappears (and the timer stops) each time the customer sends a message.
22+
* The warning disappears (and the timer resets to 0) each time the agent sends message.
23+
* The warning value must be shorter than the time-out value (we recommend at least 30 seconds).
24+
*/
25+
const warningTime: string = (await getAppSettingValue(read, AppSetting.DialogflowCustomerTimeoutWarningTime));
26+
27+
/**
28+
* Sets the amount of time that a customer has to respond to an agent message before the session ends.
29+
* The timer stops when the customer sends a message and starts again from 0 on the next agent's message.
30+
*/
31+
const timeoutTime: string = (await getAppSettingValue(read, AppSetting.DialogflowCustomerTimeoutTime));
32+
33+
// ------ When agent sends message -----
34+
// Send new timeout msg and reset previous timeout
35+
36+
// ------ When customer sends message -----
37+
// Send timeout msg to cancel previous timeout
38+
39+
// On Timeout : Close chat
40+
// On Warning : Show Countdown Popup in Livechat Widget
41+
42+
const timeoutWarningMessage: string = (await getAppSettingValue(read, AppSetting.DialogflowCustomerTimeoutWarningMessage));
43+
44+
if (message.sender.username === dialogflowBotUsername) {
45+
// Agent sent message
46+
if (!message.id) {
47+
return;
48+
}
49+
const user = await read.getUserReader().getByUsername(dialogflowBotUsername);
50+
const msgExtender = modify.getExtender().extendMessage(message.id, user);
51+
(await msgExtender).addCustomField('idleTimeoutConfig', {
52+
idleTimeoutAction: 'start',
53+
idleTimeoutWarningTime: warningTime,
54+
idleTimeoutTimeoutTime: timeoutTime,
55+
idleTimeoutMessage: timeoutWarningMessage,
56+
});
57+
modify.getExtender().finish(await msgExtender);
58+
} else {
59+
// Guest sent message
60+
61+
if (!message.id) {
62+
return;
63+
}
64+
const user = await read.getUserReader().getByUsername(dialogflowBotUsername);
65+
const msgExtender = modify.getExtender().extendMessage(message.id, user);
66+
(await msgExtender).addCustomField('idleTimeoutConfig', {
67+
idleTimeoutAction: 'stop',
68+
idleTimeoutWarningTime: warningTime,
69+
idleTimeoutTimeoutTime: timeoutTime,
70+
idleTimeoutMessage: timeoutWarningMessage,
71+
});
72+
modify.getExtender().finish(await msgExtender);
73+
}
74+
}
75+
};

0 commit comments

Comments
 (0)