Skip to content

Commit 98a92df

Browse files
authored
Merge pull request #33 from RocketChat/incoming-event
[NEW] add a action to trigger an event
2 parents 584166c + f28dd7f commit 98a92df

8 files changed

Lines changed: 157 additions & 11 deletions

File tree

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ The app provides API to trigger specific actions. The URL for the API can be fou
7777
2. **Handover**<br/>
7878
To perform a handover
7979
- REST API Documentation for this endpoint can be found [here](./docs/api-endpoints/perform-handover.md)
80-
3. **Send-Message**<br/>
80+
3. **Trigger Event**<br/>
81+
To trigger an event on Dialogflow
82+
- REST API Documentation for this endpoint can be found [here](./docs/api-endpoints/trigger-event.md)
83+
4. **Send-Message**<br/>
8184
To send a message as a bot to Visitor
8285
- REST API Documentation for this endpoint can be found [here](./docs/api-endpoints/send-message.md)
8386
2. Fulfillment API/Endpoint
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
**Trigger Event**
2+
----
3+
Action to Trigger an Event
4+
5+
* **URL**
6+
7+
REST API URL can be found on Apps Page <br />
8+
Sample Url for eg: <br /> `http://localhost:3000/api/apps/public/783d8e4d-b06a-409a-aaf3-b37650dc0a26/incoming`
9+
10+
* **Method:**
11+
12+
`POST`
13+
14+
* **Input Data Format**
15+
16+
`JSON`
17+
18+
* **Data Params**
19+
20+
**Required:**
21+
22+
1. `action` = `trigger-event` <br/>
23+
24+
2. `sessionId=[string]`
25+
> Note. Session Id is the same session of Dialogflow
26+
27+
3. ```bash
28+
actionData: {
29+
event: {
30+
"name": string,
31+
"parameters": {
32+
object
33+
},
34+
languageCode: string
35+
}
36+
}
37+
38+
```
39+
> The structure for this actionData is similar to [EventInput](https://cloud.google.com/dialogflow/docs/reference/rest/v2/QueryInput#eventinput)
40+
41+
42+
* **Sample Payload:**
43+
44+
```javascript
45+
{
46+
action: "trigger-event",
47+
sessionId: "uGM3uDZkAjtiBb4MA",
48+
actionData: {
49+
event: {
50+
name: "Welcome",
51+
parameters: {
52+
"name": "Sam"
53+
},
54+
languageCode: "en"
55+
}
56+
}
57+
}
58+
```
59+
60+
61+
* **Success Response:**
62+
63+
* **Code:** 200 <br />
64+
**Content:** `{ result: "Your request was processed successfully" }`
65+
66+
* **Error Response:**
67+
68+
* **Code:** 400 BAD REQUEST <br />
69+
**Content:** <br/>
70+
`{
71+
error: "Error: Session Id not present in request"
72+
}`
73+
74+
OR
75+
76+
* **Code:** 500 Internal Server Error <br />
77+
**Content:** <br />
78+
`{ error : "Error occurred while processing perform-handover. Details:- [Error Details]" }`
79+
80+
* **Sample Call:**
81+
82+
**Curl**
83+
```bash
84+
curl "http://localhost:3000/api/apps/public/21b7d3ba-031b-41d9-8ff2-fbbfa081ae90/incoming" \
85+
-X POST \
86+
-d "{\n \"action\": \"trigger-event\",\n \"sessionId\": \"uGM3uDZkAjtiBb4MA\",\n \"actionData\": {\n \"event\": {\n \"name\": \"Welcome\",\n \"parameters\": {\n \"name\": \"Sam\"\n },\n \"languageCode\": \"en\"\n }\n }\n}" \
87+
-H "Content-Type: application/json"
88+
```
89+
**HTTP**
90+
91+
```HTTP
92+
POST /api/apps/public/21b7d3ba-031b-41d9-8ff2-fbbfa081ae90/incoming HTTP/1.1
93+
Host: localhost:3000
94+
Content-Type: application/json
95+
96+
{
97+
"action": "trigger-event",
98+
"sessionId": "uGM3uDZkAjtiBb4MA",
99+
"actionData": {
100+
"event": {
101+
"name": "Welcome",
102+
"parameters": {
103+
"name": "Sam"
104+
},
105+
"languageCode": "en"
106+
}
107+
}
108+
}
109+
```

endpoints/IncomingEndpoint.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { HttpStatusCode, IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors';
22
import { ApiEndpoint, IApiEndpointInfo, IApiRequest, IApiResponse } from '@rocket.chat/apps-engine/definition/api';
33
import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat';
4+
import { IDialogflowMessage, DialogflowRequestType } from '../enum/Dialogflow';
45
import { EndpointActionNames, IActionsEndpointContent } from '../enum/Endpoints';
56
import { Headers, Response } from '../enum/Http';
67
import { Logs } from '../enum/Logs';
8+
import { Dialogflow } from '../lib/Dialogflow';
79
import { createHttpResponse } from '../lib/Http';
810
import { createDialogflowMessage } from '../lib/Message';
911
import { closeChat, performHandover } from '../lib/Room';
@@ -20,15 +22,15 @@ export class IncomingEndpoint extends ApiEndpoint {
2022
this.app.getLogger().info(Logs.ENDPOINT_RECEIVED_REQUEST);
2123

2224
try {
23-
await this.processRequest(read, modify, persis, request.content);
25+
await this.processRequest(read, modify, http, request.content);
2426
return createHttpResponse(HttpStatusCode.OK, { 'Content-Type': Headers.CONTENT_TYPE_JSON }, { result: Response.SUCCESS });
2527
} catch (error) {
2628
this.app.getLogger().error(Logs.ENDPOINT_REQUEST_PROCESSING_ERROR, error);
2729
return createHttpResponse(HttpStatusCode.INTERNAL_SERVER_ERROR, { 'Content-Type': Headers.CONTENT_TYPE_JSON }, { error: error.message });
2830
}
2931
}
3032

31-
private async processRequest(read: IRead, modify: IModify, persis: IPersistence, endpointContent: IActionsEndpointContent) {
33+
private async processRequest(read: IRead, modify: IModify, http: IHttp, endpointContent: IActionsEndpointContent) {
3234

3335
const { action, sessionId } = endpointContent;
3436
if (!sessionId) { throw new Error(Logs.INVALID_SESSION_ID); }
@@ -43,6 +45,18 @@ export class IncomingEndpoint extends ApiEndpoint {
4345
const { visitor: { token: visitorToken } } = room;
4446
await performHandover(modify, read, sessionId, visitorToken, targetDepartment);
4547
break;
48+
case EndpointActionNames.TRIGGER_EVENT:
49+
const { actionData: { event = null } = {} } = endpointContent;
50+
if (!event) { throw new Error(Logs.INVALID_EVENT_DATA); }
51+
52+
try {
53+
const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, sessionId, event, DialogflowRequestType.EVENT);
54+
await createDialogflowMessage(sessionId, read, modify, response);
55+
} catch (error) {
56+
this.app.getLogger().error(`${Logs.DIALOGFLOW_REST_API_ERROR} ${error.message}`);
57+
throw new Error(`${Logs.DIALOGFLOW_REST_API_ERROR} ${error.message}`);
58+
}
59+
break;
4660
case EndpointActionNames.SEND_MESSAGE:
4761
const { actionData: { messages = null } = {} } = endpointContent;
4862
if (!messages) { throw new Error(Logs.INVALID_MESSAGES); }

enum/Dialogflow.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ export interface IDialogflowAccessToken {
1414
expiration: Date;
1515
}
1616

17+
export interface IDialogflowEvent {
18+
name: string;
19+
parameters?: any;
20+
languageCode: string;
21+
}
22+
1723
export enum QuickReplyContentType {
1824
TEXT = 'text',
1925
}
@@ -38,3 +44,8 @@ export enum Base64 {
3844
export enum LanguageCode {
3945
EN = 'en',
4046
}
47+
48+
export enum DialogflowRequestType {
49+
MESSAGE = 'message',
50+
EVENT = 'event',
51+
}

enum/Endpoints.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { IDialogflowQuickReplies } from './Dialogflow';
1+
import { IDialogflowEvent, IDialogflowQuickReplies } from './Dialogflow';
22

33
export interface IActionsEndpointContent {
44
action: EndpointActionNames;
55
sessionId: string;
66
actionData?: {
77
targetDepartment?: string;
8+
event?: IDialogflowEvent;
89
messages: Array<string | IDialogflowQuickReplies>;
910
};
1011
}
1112

1213
export enum EndpointActionNames {
1314
CLOSE_CHAT = 'close-chat',
1415
HANDOVER = 'handover',
16+
TRIGGER_EVENT = 'trigger-event',
1517
SEND_MESSAGE = 'send-message',
1618
}

enum/Logs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export enum Logs {
66
INVALID_BOT_USERNAME_SETTING = 'The Bot User does not exist.',
77
INVALID_VISITOR_TOKEN = 'Error: Visitor Token not valid',
88
INVALID_DEPARTMENT_NAME = 'Error: Department Name is not valid',
9+
INVALID_EVENT_DATA = 'Error! Event Data not valid',
910
INVALID_MESSAGES = 'Error! Messages data not present or in wrong format. Kindly refer the api documentation.',
1011
ENDPOINT_REQUEST_PROCESSING_ERROR = 'Error occurred while processing the request. Details:- ',
1112
INVALID_ENDPOINT_ACTION = 'Error!! Invalid Action type',

handler/PostMessageSentHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IApp } from '@rocket.chat/apps-engine/definition/IApp';
33
import { ILivechatMessage, ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat';
44
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';
55
import { AppSetting, DefaultMessage } from '../config/Settings';
6-
import { IDialogflowMessage } from '../enum/Dialogflow';
6+
import { DialogflowRequestType, IDialogflowMessage } from '../enum/Dialogflow';
77
import { Logs } from '../enum/Logs';
88
import { Dialogflow } from '../lib/Dialogflow';
99
import { createDialogflowMessage, createMessage } from '../lib/Message';
@@ -48,7 +48,7 @@ export class PostMessageSentHandler {
4848

4949
let response: IDialogflowMessage;
5050
try {
51-
response = (await Dialogflow.sendMessage(this.http, this.read, this.modify, rid, text));
51+
response = (await Dialogflow.sendRequest(this.http, this.read, this.modify, rid, text, DialogflowRequestType.MESSAGE));
5252
} catch (error) {
5353
this.app.getLogger().error(`${Logs.DIALOGFLOW_REST_API_ERROR} ${error.message}`);
5454

lib/Dialogflow.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { IHttp, IHttpRequest, IModify, IPersistence, IRead } from '@rocket.chat/
22
import { IRoom } from '@rocket.chat/apps-engine/definition/rooms';
33
import { createSign } from 'crypto';
44
import { AppSetting } from '../config/Settings';
5-
import { DialogflowJWT, DialogflowUrl, IDialogflowAccessToken, IDialogflowMessage, IDialogflowQuickReplies, LanguageCode } from '../enum/Dialogflow';
5+
import { DialogflowJWT, DialogflowRequestType, DialogflowUrl, IDialogflowAccessToken, IDialogflowEvent, IDialogflowMessage, IDialogflowQuickReplies, LanguageCode } from '../enum/Dialogflow';
66
import { Headers } from '../enum/Http';
77
import { Logs } from '../enum/Logs';
88
import { base64urlEncode } from './Helper';
@@ -12,23 +12,29 @@ import { getAppSettingValue } from './Settings';
1212

1313
class DialogflowClass {
1414
private jwtExpiration: Date;
15-
public async sendMessage(http: IHttp,
15+
public async sendRequest(http: IHttp,
1616
read: IRead,
1717
modify: IModify,
1818
sessionId: string,
19-
messageText: string): Promise<IDialogflowMessage> {
19+
request: IDialogflowEvent | string,
20+
requestType: DialogflowRequestType): Promise<IDialogflowMessage> {
2021
const serverURL = await this.getServerURL(read, modify, http, sessionId);
2122

23+
const queryInput = {
24+
...requestType === DialogflowRequestType.EVENT && { event: request },
25+
...requestType === DialogflowRequestType.MESSAGE && { text: { languageCode: LanguageCode.EN, text: request } },
26+
};
27+
2228
const httpRequestContent: IHttpRequest = createHttpRequest(
2329
{ 'Content-Type': Headers.CONTENT_TYPE_JSON, 'Accept': Headers.ACCEPT_JSON },
24-
{ queryInput: { text: { languageCode: LanguageCode.EN, text: messageText } } },
30+
{ queryInput },
2531
);
2632

2733
try {
2834
const response = await http.post(serverURL, httpRequestContent);
2935
return this.parseRequest(response.data);
3036
} catch (error) {
31-
throw new Error(Logs.HTTP_REQUEST_ERROR);
37+
throw new Error(`${ Logs.HTTP_REQUEST_ERROR }`);
3238
}
3339
}
3440

0 commit comments

Comments
 (0)