This repository has been archived by the owner on Oct 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
server.js
executable file
·146 lines (116 loc) · 4.71 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
* Copyright 2018 Artificial Solutions. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const dotenv = require('dotenv');
dotenv.config();
const { BasicCard, actionssdk } = require('actions-on-google');
const express = require('express');
const bodyParser = require('body-parser');
const TIE = require('@artificialsolutions/tie-api-client');
const teneoApi = TIE.init(process.env.TENEO_ENGINE_URL);
const assistant = actionssdk();
// initialise session handler, to store mapping between conversationId and engine session id
const sessionHandler = SessionHandler();
// Hande main intent
assistant.intent('actions.intent.MAIN', async conv => {
// send message to teneo and return response
await handleMessage(conv);
})
// handle text inputs
assistant.intent('actions.intent.TEXT', async conv => {
// send message to teneo and return response
await handleMessage(conv);
})
async function handleMessage(conv) {
// get the id of the conversation so we can map it to an engine session
var userToken = conv.id;
// check if we have stored an engine sessionid for this user
var teneoSessionId = "";
if (sessionHandler.getSession(userToken)) {
teneoSessionId = sessionHandler.getSession(userToken);
}
console.log("teneoSessionId: " + teneoSessionId);
// message can be empty, mostly for main intent
let message = "";
if (conv.input.raw) {
message = conv.input.raw;
}
console.log(`Got message '${message}' for session: '${teneoSessionId}'`);
// get answer to message from teneo using sessionId stored in user storage
const teneoResponse = await teneoApi.sendInput(teneoSessionId, {
text: message,
'channel': 'googleactions'
});
if (teneoResponse.status == 0) {
console.log(`Got Teneo Engine response '${teneoResponse.output.text}' with session ${teneoResponse.sessionId}`);
// your bot can use output parameters to populate rich responses
// you would find those in teneoResponse.output.parameters
// store engine session id session storage
console.log("storing session [" + teneoResponse.sessionId + "] for token [" + userToken + "]")
sessionHandler.setSession(userToken, teneoResponse.sessionId);
// check if we need to close the conversation
const outputType = teneoResponse.output.parameters.gaOutputType;
// send teneo answer to assistant
if (outputType == 'close') {
conv.close(teneoResponse.output.text);
} else {
conv.ask(teneoResponse.output.text);
}
// parse engine output parameter 'googleactions' with rich response data
// but only if assistant device supports rich responses
// https://developers.google.com/actions/assistant/responses#rich-responses
if (teneoResponse.output.parameters.googleactions && conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT')) {
try {
// send rich response to assistant
conv.ask(JSON.parse(teneoResponse.output.parameters.googleactions));
} catch (error_attach) {
console.error(`Failed when parsing attachment JSON`, error_attach);
}
}
} else {
// engine returned an error
conv.close("I'm sorry, something went wrong.");
}
}
/***
* SESSION HANDLER
***/
function SessionHandler() {
// Map the conversation id id to the teneo engine session id.
// This code keeps the map in memory, which is ok for testing purposes
// For production usage it is advised to make use of more resilient storage mechanisms like redis
const sessionMap = new Map();
return {
getSession: (userId) => {
if (sessionMap.size > 0) {
return sessionMap.get(userId);
}
else {
return "";
}
},
setSession: (userId, sessionId) => {
sessionMap.set(userId, sessionId)
}
};
}
const expressApp = express().use(bodyParser.json());
expressApp.post('/', assistant);
expressApp.get('/', function (req, res) {
res.send('Connector running');
});
expressApp.listen(process.env.PORT || 3769);
console.log("listening on port " + process.env.PORT);