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 0
/
server.js
156 lines (125 loc) · 3.94 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
147
148
149
150
151
152
153
154
155
156
/**
* Copyright 2019 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.
*/
require('dotenv').config();
const express = require('express');
const http = require('http');
const wechat = require('wechat');
const app = express();
const TIE = require('@artificialsolutions/tie-api-client');
const config = {
token: process.env.TOKEN,
appid: process.env.APP_ID,
teneoURL: process.env.TENEO_ENGINE_URL
};
const teneoApi = TIE.init(config.teneoURL);
// initialise session handler, to store mapping between WeChat and engine session id
const sessionHandler = SessionHandler();
app.use(express.query());
app.use('/wechat', wechat(config, async function (req, res, next) {
// All WeChat related info is in req.weixin
var message = req.weixin;
console.log(message);
const wechatUserID = message.FromUserName;
// check if we have stored an engine sessionid for this user
const teneoSessionId = sessionHandler.getSession(wechatUserID);
// get user's input
let userInput = message.Content;
// send input to engine using the stored sessionid and retreive response
const teneoResponse = await teneoApi.sendInput(teneoSessionId, { 'text': userInput });
// store engine sessionid for this user
sessionHandler.setSession(wechatUserID, teneoResponse.sessionId);
// Wechat expects you to respond, or else it will tell the user that the service is unavailable after three tries.
res.reply(teneoResponse.output.text)
}));
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
res.status(err.status || 500);
res.render('error');
});
var port = process.env.PORT || '3000';
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
server.on('error', onError);
server.on('listening', onListening);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
console.log('Listening on ' + bind);
}
/***
* SESSION HANDLER
***/
function SessionHandler() {
// Map the Webchat Sid 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)
}
};
}