Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions DialogflowApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '@rocket.chat/apps-engine/definition/accessors';
import { ApiSecurity, ApiVisibility } from '@rocket.chat/apps-engine/definition/api';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { ILivechatMessage } from '@rocket.chat/apps-engine/definition/livechat';
import { ILivechatMessage, ILivechatEventContext, IPostLivechatAgentAssigned } from '@rocket.chat/apps-engine/definition/livechat';
import { IPostMessageSent } from '@rocket.chat/apps-engine/definition/messages';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { ISetting } from '@rocket.chat/apps-engine/definition/settings';
Expand All @@ -20,9 +20,10 @@ import { FulfillmentsEndpoint } from './endpoints/FulfillmentsEndpoint';
import { IncomingEndpoint } from './endpoints/IncomingEndpoint';
import { ExecuteLivechatBlockActionHandler } from './handler/ExecuteLivechatBlockActionHandler';
import { OnSettingUpdatedHandler } from './handler/OnSettingUpdatedHandler';
import { OnAgentAssignedHandler } from './handler/OnAgentAssignedHandler';
import { PostMessageSentHandler } from './handler/PostMessageSentHandler';

export class DialogflowApp extends App implements IPostMessageSent, IUIKitLivechatInteractionHandler {
export class DialogflowApp extends App implements IPostMessageSent, IPostLivechatAgentAssigned, IUIKitLivechatInteractionHandler {
constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {
super(info, logger, accessors);
}
Expand All @@ -45,6 +46,15 @@ export class DialogflowApp extends App implements IPostMessageSent, IUIKitLivech
await handler.run();
}

public async executePostLivechatAgentAssigned(context: ILivechatEventContext,
read: IRead,
http: IHttp,
persis: IPersistence,
modify: IModify): Promise<void> {
const handler = new OnAgentAssignedHandler(this, context, read, http, persis, modify);
await handler.run();
}

public async onSettingUpdated(setting: ISetting, configurationModify: IConfigurationModify, read: IRead, http: IHttp): Promise<void> {
const onSettingUpdatedHandler: OnSettingUpdatedHandler = new OnSettingUpdatedHandler(this, read, http);
await onSettingUpdatedHandler.run();
Expand Down
31 changes: 31 additions & 0 deletions config/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export enum AppSetting {
DialogflowServiceUnavailableMessage = 'dialogflow_service_unavailable_message',
DialogflowCloseChatMessage = 'dialogflow_close_chat_message',
DialogflowHideQuickReplies = 'dialogflow_hide_quick_replies',
DialogflowEnableChatClosedByVisitorEvent = 'dialogflow_enable_chat_closed_by_visitor_event',
DialogflowChatClosedByVisitorEventName = 'dialogflow_chat_closed_by_visitor_event_name',
DialogflowWelcomeIntentOnStart = 'dialogflow_welcome_intent_on_start',
}

export enum DefaultMessage {
Expand Down Expand Up @@ -108,4 +111,32 @@ export const settings: Array<ISetting> = [
i18nDescription: 'dialogflow_hide_quick_replies_description',
required: true,
},
{
id: AppSetting.DialogflowEnableChatClosedByVisitorEvent,
public: true,
type: SettingType.BOOLEAN,
packageValue: true,
value: true,
i18nLabel: 'dialogflow_enable_chat_closed_by_visitor_event',
i18nDescription: 'dialogflow_enable_chat_closed_by_visitor_event_description',
required: false,
},
{
id: AppSetting.DialogflowChatClosedByVisitorEventName,
public: true,
type: SettingType.STRING,
packageValue: 'closed_by_visitor',
i18nLabel: 'dialogflow_chat_closed_by_visitor_event_name',
i18nDescription: 'dialogflow_chat_closed_by_visitor_event_name_description',
required: false,
},
{
id: AppSetting.DialogflowWelcomeIntentOnStart,
public: true,
type: SettingType.BOOLEAN,
packageValue: false,
i18nLabel: 'dialogflow_welcome_intent_on_start',
i18nDescription: 'dialogflow_welcome_intent_on_start_description',
required: true,
},
];
4 changes: 4 additions & 0 deletions enum/Dialogflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,7 @@ export enum DialogflowRequestType {
MESSAGE = 'message',
EVENT = 'event',
}

export enum Message {
CLOSED_BY_VISITOR = 'Closed by visitor',
}
58 changes: 58 additions & 0 deletions handler/OnAgentAssignedHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors';
import { IApp } from '@rocket.chat/apps-engine/definition/IApp';
import { ILivechatEventContext, ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat';
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';
import { AppSetting, DefaultMessage } from '../config/Settings';
import { DialogflowRequestType, IDialogflowMessage } from '../enum/Dialogflow';
import { Logs } from '../enum/Logs';
import { Dialogflow } from '../lib/Dialogflow';
import { createDialogflowMessage, createMessage } from '../lib/Message';
import { getAppSettingValue } from '../lib/Settings';

export class OnAgentAssignedHandler {
constructor(private readonly app: IApp,
private readonly context: ILivechatEventContext,
private readonly read: IRead,
private readonly http: IHttp,
private readonly persis: IPersistence,
private readonly modify: IModify) {}

public async run() {
const { room } = this.context;
const livechatRoom = room as ILivechatRoom;

const { id: rid, type, servedBy, isOpen } = livechatRoom;

const DialogflowBotUsername: string = await getAppSettingValue(this.read, AppSetting.DialogflowBotUsername);
const { value: sendWelcomeEvent } = await this.read.getEnvironmentReader().getSettings().getById(AppSetting.DialogflowWelcomeIntentOnStart);

if (!type || type !== RoomType.LIVE_CHAT) {
return;
}

if (!isOpen || !sendWelcomeEvent) {
return;
}

if (!servedBy || servedBy.username !== DialogflowBotUsername) {
return;
}

try {
const event = { name: "Welcome", languageCode: "en" };
const response: IDialogflowMessage = await Dialogflow.sendRequest(this.http, this.read, this.modify, rid, event, DialogflowRequestType.EVENT);
await createDialogflowMessage(rid, this.read, this.modify, response);
} catch (error) {
this.app.getLogger().error(`${Logs.DIALOGFLOW_REST_API_ERROR} ${error.message}`);

const serviceUnavailable: string = await getAppSettingValue(this.read, AppSetting.DialogflowServiceUnavailableMessage);

await createMessage(rid,
this.read,
this.modify,
{ text: serviceUnavailable ? serviceUnavailable : DefaultMessage.DEFAULT_DialogflowServiceUnavailableMessage });

return;
}
}
}
22 changes: 21 additions & 1 deletion handler/PostMessageSentHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { IApp } from '@rocket.chat/apps-engine/definition/IApp';
import { ILivechatMessage, ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat';
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';
import { AppSetting, DefaultMessage } from '../config/Settings';
import { DialogflowRequestType, IDialogflowMessage } from '../enum/Dialogflow';
import { DialogflowRequestType, IDialogflowMessage, LanguageCode, Message } from '../enum/Dialogflow';
import { Logs } from '../enum/Logs';
import { Dialogflow } from '../lib/Dialogflow';
import { createDialogflowMessage, createMessage } from '../lib/Message';
Expand All @@ -26,6 +26,10 @@ export class PostMessageSentHandler {

const DialogflowBotUsername: string = await getAppSettingValue(this.read, AppSetting.DialogflowBotUsername);

if (text === Message.CLOSED_BY_VISITOR) {
this.handleClosedByVisitor(rid);
}

if (!type || type !== RoomType.LIVE_CHAT) {
return;
}
Expand Down Expand Up @@ -71,4 +75,20 @@ export class PostMessageSentHandler {
}
return resetFallbackIntent(this.read, this.modify, rid);
}

private async handleClosedByVisitor(rid: string) {
const DialogflowEnableChatClosedByVisitorEvent: boolean = await getAppSettingValue(this.read, AppSetting.DialogflowEnableChatClosedByVisitorEvent);
const DialogflowChatClosedByVisitorEventName: string = await getAppSettingValue(this.read, AppSetting.DialogflowChatClosedByVisitorEventName);
if (DialogflowEnableChatClosedByVisitorEvent) {
try {
let res: IDialogflowMessage;
res = (await Dialogflow.sendRequest(this.http, this.read, this.modify, rid, {
name: DialogflowChatClosedByVisitorEventName,
languageCode: LanguageCode.EN,
}, DialogflowRequestType.EVENT));
} catch (error) {
this.app.getLogger().error(`${Logs.DIALOGFLOW_REST_API_ERROR} ${error.message}`);
}
}
}
}
8 changes: 7 additions & 1 deletion i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,11 @@
"dialogflow_close_chat_message": "Close Chat Message",
"dialogflow_close_chat_message_description": "This message will be sent automatically when a chat is closed",
"dialogflow_hide_quick_replies": "Hide Quick Replies",
"dialogflow_hide_quick_replies_description": "If enabled, then all quick-replies will hide when a visitor clicks on any one of them"
"dialogflow_hide_quick_replies_description": "If enabled, then all quick-replies will hide when a visitor clicks on any one of them",
"dialogflow_enable_chat_closed_by_visitor_event": "Enable Dialogflow Event When Visitor Ends Chat",
"dialogflow_enable_chat_closed_by_visitor_event_description": "If enabled, then a dialogflow event will be triggered when visitor ends chat",
"dialogflow_chat_closed_by_visitor_event_name": "Dialogflow Event Name When Visitor Ends Chat",
"dialogflow_chat_closed_by_visitor_event_name_description": "The bot will trigger this dialogflow event when visitor ends chat",
"dialogflow_welcome_intent_on_start": "Send Welcome Intent",
"dialogflow_welcome_intent_on_start_description": "If enabled, then a welcome message will be sent when bot is assigned to any visitor"
}