Commit 58a70b79 authored by murtaza98's avatar murtaza98

add incoming endpoint to close-chat and perform handover

parent c8a37f6b
......@@ -7,11 +7,13 @@ import {
IPersistence,
IRead,
} 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 { IPostMessageSent } from '@rocket.chat/apps-engine/definition/messages';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { settings } from './config/Settings';
import { IncomingEndpoint } from './endpoints/IncomingEndpoint';
import { PostMessageSentHandler } from './handler/PostMessageSentHandler';
export class AppsRasaApp extends App implements IPostMessageSent {
......@@ -29,6 +31,13 @@ export class AppsRasaApp extends App implements IPostMessageSent {
}
protected async extendConfiguration(configuration: IConfigurationExtend): Promise<void> {
configuration.api.provideApi({
visibility: ApiVisibility.PUBLIC,
security: ApiSecurity.UNSECURE,
endpoints: [
new IncomingEndpoint(this),
],
});
await Promise.all(settings.map((setting) => configuration.settings.provideSetting(setting)));
}
}
......@@ -4,6 +4,8 @@ export enum AppSetting {
RasaBotUsername = 'rasa_bot_username',
RasaServerUrl = 'rasa_server_url',
RasaServiceUnavailableMessage = 'rasa_service_unavailable_message',
RasaHandoverMessage = 'rasa_handover_message',
RasaCloseChatMessage = 'rasa_close_chat_message',
}
export const settings: Array<ISetting> = [
......@@ -32,4 +34,22 @@ export const settings: Array<ISetting> = [
i18nDescription: 'rasa_service_unavailable_message_description',
required: false,
},
{
id: AppSetting.RasaCloseChatMessage,
public: true,
type: SettingType.STRING,
packageValue: '',
i18nLabel: 'rasa_close_chat_message',
i18nDescription: 'rasa_close_chat_message_description',
required: false,
},
{
id: AppSetting.RasaHandoverMessage,
public: true,
type: SettingType.STRING,
packageValue: '',
i18nLabel: 'rasa_handover_message',
i18nDescription: 'rasa_handover_message_description',
required: false,
},
];
import { HttpStatusCode, IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors';
import { ApiEndpoint, IApiEndpointInfo, IApiRequest, IApiResponse } from '@rocket.chat/apps-engine/definition/api';
import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat';
import { EndpointActionNames, IActionsEndpointContent } from '../enum/Endpoints';
import { Headers } from '../enum/Http';
import { createHttpResponse } from '../lib/Http';
import { closeChat, performHandover } from '../lib/Room';
export class IncomingEndpoint extends ApiEndpoint {
public path = 'incoming';
public async post(request: IApiRequest,
endpoint: IApiEndpointInfo,
read: IRead,
modify: IModify,
http: IHttp,
persis: IPersistence): Promise<IApiResponse> {
this.app.getLogger().info('Endpoint recieved an request');
try {
await this.processRequest(read, modify, persis, request.content);
return createHttpResponse(HttpStatusCode.OK, { 'Content-Type': Headers.CONTENT_TYPE_JSON }, { result: 'Success' });
} catch (error) {
this.app.getLogger().error('Error occurred while processing the request. Details:- ', error);
return createHttpResponse(HttpStatusCode.INTERNAL_SERVER_ERROR, { 'Content-Type': Headers.CONTENT_TYPE_JSON }, { error: error.message });
}
}
private async processRequest(read: IRead, modify: IModify, persis: IPersistence, endpointContent: IActionsEndpointContent) {
const { action, sessionId } = endpointContent;
if (!sessionId) {
throw new Error('Error!! Session Id not present in payload');
}
switch (action) {
case EndpointActionNames.CLOSE_CHAT:
await closeChat(modify, read, sessionId);
break;
case EndpointActionNames.HANDOVER:
const { actionData: { targetDepartment = '' } = {} } = endpointContent;
const room = await read.getRoomReader().getById(sessionId) as ILivechatRoom;
if (!room) { throw new Error('Error! Session Id not valid'); }
const { visitor: { token: visitorToken } } = room;
await performHandover(modify, read, sessionId, visitorToken, targetDepartment);
break;
default:
throw new Error('Error!! Invalid Action type');
}
}
}
export interface IActionsEndpointContent {
action: EndpointActionNames;
sessionId: string;
actionData?: {
targetDepartment?: string;
};
}
export enum EndpointActionNames {
CLOSE_CHAT = 'close-chat',
HANDOVER = 'handover',
}
......@@ -2,5 +2,9 @@
"bot_username": "Bot Username",
"rasa_server_url": "Rasa Server Url",
"rasa_service_unavailable_message": "Service Unavailable Message",
"rasa_service_unavailable_message_description": "The Bot will send this message to Visitor if service is unavailable"
"rasa_service_unavailable_message_description": "The Bot will send this message to Visitor if service is unavailable",
"rasa_handover_message": "Handover Message",
"rasa_handover_message_description": "The Bot will send this message to Visitor upon handover",
"rasa_close_chat_message": "Close Chat Message",
"rasa_close_chat_message_description": "This message will be sent automatically when a chat is closed"
}
import { IModify, IRead } from '@rocket.chat/apps-engine/definition/accessors';
import { IDepartment, ILivechatRoom, ILivechatTransferData, IVisitor } from '@rocket.chat/apps-engine/definition/livechat';
import { IRoom } from '@rocket.chat/apps-engine/definition/rooms';
import { AppSetting } from '../config/Settings';
import { createMessage } from './Message';
import { getAppSettingValue } from './Setting';
export const updateRoomCustomFields = async (rid: string, data: any, read: IRead, modify: IModify): Promise<any> => {
if (!rid) {
return;
}
const room = await read.getRoomReader().getById(rid);
if (!room) { throw new Error(`Invalid room id ${rid}`); }
const botUserName = await getAppSettingValue(read, AppSetting.RasaBotUsername);
if (!botUserName) { throw new Error('The Bot Username setting is not defined.'); }
const user = await read.getUserReader().getByUsername(botUserName);
if (!user) { throw new Error('The Bot User does not exist.'); }
let { customFields = {} } = room;
customFields = Object.assign(customFields, data);
const roomBuilder = await modify.getUpdater().room(rid, user);
roomBuilder.setCustomFields(customFields);
try {
modify.getUpdater().finish(roomBuilder);
} catch (error) {
console.error(error);
}
};
export const closeChat = async (modify: IModify, read: IRead, rid: string) => {
const room: IRoom = (await read.getRoomReader().getById(rid)) as IRoom;
if (!room) { throw new Error('Error: Room Id not valid'); }
const closeChatMessage = await getAppSettingValue(read, AppSetting.RasaCloseChatMessage);
const result = await modify.getUpdater().getLivechatUpdater().closeRoom(room, closeChatMessage ? closeChatMessage : '');
if (!result) { throw new Error('Error: Internal Server Error. Could not close the chat'); }
};
export const performHandover = async (modify: IModify, read: IRead, rid: string, visitorToken: string, targetDepartmentName?: string) => {
const handoverMessage: string = await getAppSettingValue(read, AppSetting.RasaHandoverMessage);
await createMessage(rid, read, modify, { text: handoverMessage ? handoverMessage : '' });
const room: ILivechatRoom = (await read.getRoomReader().getById(rid)) as ILivechatRoom;
if (!room) { throw new Error('Error: Room Id not valid'); }
const visitor: IVisitor = (await read.getLivechatReader().getLivechatVisitorByToken(visitorToken)) as IVisitor;
if (!visitor) { throw new Error('Error: Visitor Id not valid'); }
const livechatTransferData: ILivechatTransferData = {
currentRoom: room,
};
// Fill livechatTransferData.targetDepartment param if required
if (targetDepartmentName) {
const targetDepartment: IDepartment = (await read.getLivechatReader().getLivechatDepartmentByIdOrName(targetDepartmentName)) as IDepartment;
if (!targetDepartment) { throw new Error('Error: Department Name is not valid'); }
livechatTransferData.targetDepartment = targetDepartment.id;
}
const result = await modify.getUpdater().getLivechatUpdater().transferVisitor(visitor, livechatTransferData)
.catch((error) => {
throw new Error('Error occured while processing handover. Details' + error);
});
if (!result) {
const offlineMessage: string = await getAppSettingValue(read, AppSetting.RasaServiceUnavailableMessage);
await createMessage(rid, read, modify, { text: offlineMessage ? offlineMessage : '' });
}
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment