@tiledesk/tiledesk-server 2.10.87 → 2.10.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/app.js +4 -0
- package/errorCodes.js +6 -0
- package/event/botEvent.js +89 -42
- package/jobsManager.js +4 -1
- package/models/chatbotTemplates.js +22 -0
- package/models/faq.js +14 -1
- package/models/faq_kb.js +64 -2
- package/models/flowLogs.js +64 -0
- package/models/user.js +7 -0
- package/models/webhook.js +30 -0
- package/package.json +4 -4
- package/routes/auth.js +1 -1
- package/routes/faq.js +6 -0
- package/routes/faq_kb.js +123 -85
- package/routes/logs.js +80 -3
- package/routes/request.js +2 -2
- package/routes/users.js +3 -0
- package/routes/webhook.js +54 -25
- package/routes/webhooks.js +119 -2
- package/services/chatbotService.js +24 -18
- package/services/faqService.js +35 -331
- package/services/logsService.js +59 -0
- package/services/userService.js +3 -2
- package/services/webhookService.js +21 -2
- package/template/chatbot/blank.js +79 -0
- package/template/chatbot/blank_copilot.js +43 -0
- package/template/chatbot/blank_voice.js +108 -0
- package/template/chatbot/blank_voice_twilio.js +115 -0
- package/template/chatbot/blank_webhook.js +43 -0
- package/template/chatbot/empty.js +3 -0
- package/template/chatbot/example.js +88 -0
- package/template/chatbot/handoff.js +25 -0
- package/template/chatbot/index.js +12 -0
- package/template/chatbot/official_copilot.js +717 -0
- package/test/faqkbRoute.js +165 -23
- package/test/webhookRoute.js +247 -2
- package/utils/TdCache.js +3 -3
package/routes/webhook.js
CHANGED
@@ -11,6 +11,8 @@ const httpUtil = require('../utils/httpUtil');
|
|
11
11
|
var jwt = require('jsonwebtoken');
|
12
12
|
const Faq_kb = require('../models/faq_kb');
|
13
13
|
const webhookService = require('../services/webhookService');
|
14
|
+
const errorCodes = require('../errorCodes');
|
15
|
+
var ObjectId = require('mongoose').Types.ObjectId;
|
14
16
|
|
15
17
|
const port = process.env.PORT || '3000';
|
16
18
|
let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/";;
|
@@ -186,6 +188,8 @@ router.all('/:webhook_id', async (req, res) => {
|
|
186
188
|
let payload = req.body;
|
187
189
|
payload.webhook_http_method = req.method;
|
188
190
|
let params = req.query;
|
191
|
+
let dev = params.dev;
|
192
|
+
delete params.dev;
|
189
193
|
if (params) {
|
190
194
|
payload.webhook_query_params = params;
|
191
195
|
}
|
@@ -200,41 +204,66 @@ router.all('/:webhook_id', async (req, res) => {
|
|
200
204
|
return res.status(404).send({ success: false, error: "Webhook not found with id " + webhook_id });
|
201
205
|
}
|
202
206
|
|
203
|
-
|
207
|
+
if (!webhook.enabled) {
|
208
|
+
winston.verbose("Webhook " + webhook_id + " is currently turned off")
|
209
|
+
return res.status(422).send({ success: false, error: "Webhook " + webhook_id + " is currently turned off"})
|
210
|
+
}
|
211
|
+
|
212
|
+
payload.request_id = "automation-request-" + webhook.id_project + "-" + new ObjectId() + "-" + webhook_id;
|
213
|
+
|
214
|
+
// To delete - Start
|
215
|
+
// This endpoint will be used only for production webhooks, so is no longer
|
216
|
+
// necessary to pass dev and redis_client to webhookService.run().
|
217
|
+
let redis_client = req.app.get('redis_client');
|
218
|
+
// and substitute currect run with the following one
|
219
|
+
//webhookService.run(webhook, payload)
|
220
|
+
// To delete - End
|
221
|
+
webhookService.run(webhook, payload, dev, redis_client).then((response) => {
|
204
222
|
return res.status(200).send(response);
|
205
223
|
}).catch((err) => {
|
206
|
-
|
207
|
-
|
224
|
+
if (err.code === errorCodes.WEBHOOK.ERRORS.NO_PRELOADED_DEV_REQUEST) {
|
225
|
+
return res.status(422).send({ success: false, message: "Development webhook is currently turned off", code: err.code })
|
226
|
+
} else {
|
227
|
+
let status = err.status || 500;
|
228
|
+
return res.status(status).send(err.data);
|
229
|
+
}
|
208
230
|
})
|
209
231
|
|
210
|
-
|
211
|
-
// winston.error("Error finding chatbot ", err);
|
212
|
-
// return res.status(500).send({ success: false, error: "Error finding chatbot with id " + webhook.chatbot_id})
|
213
|
-
// })
|
232
|
+
})
|
214
233
|
|
215
|
-
|
216
|
-
// winston.verbose("Chatbot not found with id " + webhook.chatbot_id);
|
217
|
-
// return res.status(404).send({ success: false, error: "Chatbot not found with id " + webhook.chatbot_id })
|
218
|
-
// }
|
234
|
+
router.all('/:webhook_id/dev', async (req, res) => {
|
219
235
|
|
220
|
-
|
236
|
+
let webhook_id = req.params.webhook_id;
|
237
|
+
let payload = req.body;
|
238
|
+
payload.webhook_http_method = req.method;
|
239
|
+
let params = req.query;
|
240
|
+
delete params.dev;
|
241
|
+
if (params) {
|
242
|
+
payload.webhook_query_params = params;
|
243
|
+
}
|
221
244
|
|
222
|
-
|
223
|
-
|
245
|
+
let webhook = await Webhook.findOne({ webhook_id: webhook_id }).catch((err) => {
|
246
|
+
winston.error("Error finding webhook: ", err);
|
247
|
+
return res.status(500).send({ success: false, error: err });
|
248
|
+
})
|
224
249
|
|
225
|
-
|
226
|
-
|
250
|
+
if (!webhook) {
|
251
|
+
winston.warn("Webhook not found with id " + webhook_id);
|
252
|
+
return res.status(404).send({ success: false, error: "Webhook not found with id " + webhook_id });
|
253
|
+
}
|
227
254
|
|
228
|
-
|
229
|
-
|
230
|
-
|
255
|
+
let redis_client = req.app.get('redis_client');
|
256
|
+
webhookService.run(webhook, payload, true, redis_client).then((response) => {
|
257
|
+
return res.status(200).send(response);
|
258
|
+
}).catch((err) => {
|
259
|
+
if (err.code === errorCodes.WEBHOOK.ERRORS.NO_PRELOADED_DEV_REQUEST) {
|
260
|
+
return res.status(422).send({ success: false, message: "Development webhook is currently turned off", code: err.code })
|
261
|
+
} else {
|
262
|
+
let status = err.status || 500;
|
263
|
+
return res.status(status).send(err.data);
|
264
|
+
}
|
265
|
+
})
|
231
266
|
|
232
|
-
// let response = await httpUtil.post(url, payload).catch((err) => {
|
233
|
-
// winston.error("Error calling webhook on post: ", err);
|
234
|
-
// return res.status(500).send({ success: false, error: err });
|
235
|
-
// })
|
236
|
-
|
237
|
-
// res.status(200).send(response.data);
|
238
267
|
})
|
239
268
|
|
240
269
|
async function scheduleScrape(resources) {
|
package/routes/webhooks.js
CHANGED
@@ -5,7 +5,7 @@ const { Webhook } = require('../models/webhook');
|
|
5
5
|
const httpUtil = require('../utils/httpUtil');
|
6
6
|
const { customAlphabet } = require('nanoid');
|
7
7
|
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 32);
|
8
|
-
|
8
|
+
var ObjectId = require('mongoose').Types.ObjectId;
|
9
9
|
// const port = process.env.PORT || '3000';
|
10
10
|
// let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/ext/";;
|
11
11
|
// if (process.env.TILEBOT_ENDPOINT) {
|
@@ -13,8 +13,20 @@ const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 32);
|
|
13
13
|
// }
|
14
14
|
// winston.debug("TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
|
15
15
|
|
16
|
+
router.get('/', async (req, res) => {
|
17
|
+
|
18
|
+
let id_project = req.projectid;
|
19
|
+
|
20
|
+
let webhooks = await Webhook.find({ id_project: id_project }).catch((err) => {
|
21
|
+
winston.error("Error finding webhooks: ", err);
|
22
|
+
return res.status(500).send({ success: false, error: "Error findin webhooks with for project " + id_project });
|
23
|
+
})
|
16
24
|
|
17
|
-
|
25
|
+
res.status(200).send(webhooks);
|
26
|
+
|
27
|
+
})
|
28
|
+
|
29
|
+
router.get('/:chatbot_id', async (req, res) => {
|
18
30
|
|
19
31
|
let id_project = req.projectid;
|
20
32
|
let chatbot_id = req.params.chatbot_id;
|
@@ -33,6 +45,24 @@ router.get('/:chatbot_id/', async (req, res) => {
|
|
33
45
|
|
34
46
|
})
|
35
47
|
|
48
|
+
router.get('/id/:webhook_id', async (req, res) => {
|
49
|
+
|
50
|
+
let id_project = req.projectid;
|
51
|
+
let webhook_id = req.params.webhook_id;
|
52
|
+
|
53
|
+
let webhook = await Webhook.findOne({ id_project: id_project, webhook_id: webhook_id }).catch((err) => {
|
54
|
+
winston.error("Error finding webhook: ", err);
|
55
|
+
return res.status(500).send({ success: false, error: "Error findin webhook with id " + webhook_id });
|
56
|
+
})
|
57
|
+
|
58
|
+
if (!webhook) {
|
59
|
+
winston.verbose("Webhook not found with id " + webhook_id);
|
60
|
+
return res.status(404).send({ success: false, error: "Webhook not found with id " + webhook_id });
|
61
|
+
}
|
62
|
+
|
63
|
+
res.status(200).send(webhook);
|
64
|
+
})
|
65
|
+
|
36
66
|
|
37
67
|
router.post('/', async (req, res) => {
|
38
68
|
|
@@ -40,6 +70,7 @@ router.post('/', async (req, res) => {
|
|
40
70
|
|
41
71
|
let webhook = new Webhook({
|
42
72
|
id_project: id_project,
|
73
|
+
name: "webhook-" + this.webhook_id,
|
43
74
|
chatbot_id: req.body.chatbot_id || req.body.id_faq_kb,
|
44
75
|
block_id: req.body.block_id,
|
45
76
|
copilot: req.body.copilot,
|
@@ -61,6 +92,42 @@ router.post('/', async (req, res) => {
|
|
61
92
|
|
62
93
|
})
|
63
94
|
|
95
|
+
router.post('/preload/:webhook_id', async (req, res) => {
|
96
|
+
|
97
|
+
let id_project = req.projectid;
|
98
|
+
let webhook_id = req.params.webhook_id;
|
99
|
+
let request_id = "automation-request-" + id_project + "-" + new ObjectId() + "-" + webhook_id;
|
100
|
+
let redis_client = req.app.get('redis_client');
|
101
|
+
|
102
|
+
try {
|
103
|
+
let key = "logs:webhook:" + id_project + ":" + webhook_id;
|
104
|
+
let value = JSON.stringify({ request_id: request_id });
|
105
|
+
redis_client.set(key, value, { EX: 900 });
|
106
|
+
res.status(200).send({ success: true, message: "Webhook preloaded successfully", request_id: request_id });
|
107
|
+
} catch(err) {
|
108
|
+
winston.error("Error adding key in cache ", err);
|
109
|
+
res.status(500).send({ success: false, message: "Unable to start development webhook" })
|
110
|
+
}
|
111
|
+
|
112
|
+
})
|
113
|
+
|
114
|
+
router.delete('/preload/:webhook_id', async (req, res) => {
|
115
|
+
|
116
|
+
let id_project = req.projectid;
|
117
|
+
let webhook_id = req.params.webhook_id;
|
118
|
+
let key = "logs:webhook:" + id_project + ":" + webhook_id;
|
119
|
+
let redis_client = req.app.get('redis_client');
|
120
|
+
|
121
|
+
try {
|
122
|
+
await redis_client.del(key);
|
123
|
+
res.status(200).send({ success: true, message: "Development webhook stopped" })
|
124
|
+
} catch(err) {
|
125
|
+
winston.error("Error deleting key from cache ", err);
|
126
|
+
res.status(500).send({ success: false, message: "Unable to stop development webhook" })
|
127
|
+
}
|
128
|
+
|
129
|
+
})
|
130
|
+
|
64
131
|
// router.post('/webhook_id', async (req, res) => {
|
65
132
|
|
66
133
|
// let id_project = req.projectid;
|
@@ -127,6 +194,10 @@ router.put("/:chatbot_id", async (req, res) => {
|
|
127
194
|
update.copilot = req.body.copilot;
|
128
195
|
}
|
129
196
|
|
197
|
+
if (req.body.hasOwnProperty('enabled')) {
|
198
|
+
update.enabled = req.body.enabled;
|
199
|
+
}
|
200
|
+
|
130
201
|
let updatedWebhook = await Webhook.findOneAndUpdate({ id_project: id_project, chatbot_id: chatbot_id }, update, { new: true }).catch((err) => {
|
131
202
|
winston.error("Error updating webhook ", err);
|
132
203
|
return res.status(500).send({ success: false, error: "Error updating webhook for chatbot " + chatbot_id });
|
@@ -140,6 +211,39 @@ router.put("/:chatbot_id", async (req, res) => {
|
|
140
211
|
res.status(200).send(updatedWebhook);
|
141
212
|
})
|
142
213
|
|
214
|
+
router.put('/update/:webhook_id', async (req, res) => {
|
215
|
+
|
216
|
+
let id_project = req.projectid;
|
217
|
+
let webhook_id = req.params.webhook_id;
|
218
|
+
|
219
|
+
let update = {};
|
220
|
+
|
221
|
+
if (req.body.hasOwnProperty("async")) {
|
222
|
+
update.async = req.body.async;
|
223
|
+
}
|
224
|
+
|
225
|
+
if (req.body.hasOwnProperty("copilot")) {
|
226
|
+
update.copilot = req.body.copilot;
|
227
|
+
}
|
228
|
+
|
229
|
+
if (req.body.hasOwnProperty('enabled')) {
|
230
|
+
update.enabled = req.body.enabled;
|
231
|
+
}
|
232
|
+
|
233
|
+
let updatedWebhook = await Webhook.findOneAndUpdate({ id_project: id_project, webhook_id: webhook_id }, update, { new: true }).catch((err) => {
|
234
|
+
winston.error("Error updating webhook ", err);
|
235
|
+
return res.status(500).send({ success: false, error: "Error updating webhook for chatbot " + chatbot_id });
|
236
|
+
})
|
237
|
+
|
238
|
+
if (!updatedWebhook) {
|
239
|
+
winston.verbose("Webhook not found with id " + webhook_id);
|
240
|
+
return res.status(404).send({ success: false, error: "Webhook not found with id " + webhook_id });
|
241
|
+
}
|
242
|
+
|
243
|
+
res.status(200).send(updatedWebhook);
|
244
|
+
|
245
|
+
})
|
246
|
+
|
143
247
|
router.delete("/:chatbot_id", async (req, res) => {
|
144
248
|
|
145
249
|
let id_project = req.projectid;
|
@@ -153,5 +257,18 @@ router.delete("/:chatbot_id", async (req, res) => {
|
|
153
257
|
res.status(200).send({ success: true, message: "Webhook for chatbot " + chatbot_id + " deleted successfully" });
|
154
258
|
})
|
155
259
|
|
260
|
+
router.delete("/delete/:webhook_id", async (req, res) => {
|
261
|
+
|
262
|
+
let id_project = req.projectid;
|
263
|
+
let webhook_id = req.params.webhook_id;
|
264
|
+
|
265
|
+
await Webhook.deleteOne({ id_project: id_project, webhook_id: webhook_id }).catch((err) => {
|
266
|
+
winston.error("Error deleting webhook ", err);
|
267
|
+
return res.status(500).send({ success: false, error: "Error deleting webhook with id " + webhook_id });
|
268
|
+
})
|
269
|
+
|
270
|
+
res.status(200).send({ success: true, message: "Webhook " + webhook_id + " deleted successfully" });
|
271
|
+
})
|
272
|
+
|
156
273
|
|
157
274
|
module.exports = router;
|
@@ -1,15 +1,13 @@
|
|
1
1
|
const axios = require("axios").default;
|
2
2
|
const winston = require('../config/winston');
|
3
|
-
|
3
|
+
let Faq_kb = require("../models/faq_kb");
|
4
4
|
|
5
5
|
class ChatbotService {
|
6
6
|
|
7
|
-
constructor() {
|
8
|
-
|
9
|
-
}
|
7
|
+
constructor() {}
|
10
8
|
|
11
9
|
async fork(id_faq_kb, api_url, token, project_id) {
|
12
|
-
winston.debug("
|
10
|
+
winston.debug("(ChatbotService) fork");
|
13
11
|
|
14
12
|
return await axios({
|
15
13
|
url: api_url + '/' + project_id + '/faq_kb/fork/'+id_faq_kb+"?projectid="+project_id+"&public=false&globals=true",
|
@@ -20,10 +18,10 @@ class ChatbotService {
|
|
20
18
|
// data: chatbot,
|
21
19
|
method: 'POST'
|
22
20
|
}).then((resbody) => {
|
23
|
-
winston.debug("(
|
21
|
+
winston.debug("(ChatbotService) fork resbody: ", resbody.data);
|
24
22
|
return resbody.data;
|
25
23
|
}).catch((err) => {
|
26
|
-
winston.error("(
|
24
|
+
winston.error("(ChatbotService) fork error " + err);
|
27
25
|
return err;
|
28
26
|
})
|
29
27
|
|
@@ -31,7 +29,7 @@ class ChatbotService {
|
|
31
29
|
|
32
30
|
async getBotById(id_faq_kb, published, api_url, chatbot_templates_api_url, token, project_id, globals) {
|
33
31
|
|
34
|
-
winston.debug("
|
32
|
+
winston.debug("(ChatbotService) getBotById");
|
35
33
|
|
36
34
|
// private bot
|
37
35
|
if (published == "false") {
|
@@ -44,11 +42,11 @@ class ChatbotService {
|
|
44
42
|
},
|
45
43
|
method: 'GET'
|
46
44
|
}).then((resbody) => {
|
47
|
-
winston.debug("(
|
45
|
+
winston.debug("(ChatbotService) forking private chatbot " + resbody.data.name)
|
48
46
|
let chatbot = resbody.data;
|
49
47
|
return chatbot;
|
50
48
|
}).catch((err) => {
|
51
|
-
winston.error('(
|
49
|
+
winston.error('(ChatbotService) FAQ_KB EXPORTJSON ERROR ' + err);
|
52
50
|
return err;
|
53
51
|
})
|
54
52
|
|
@@ -62,11 +60,11 @@ class ChatbotService {
|
|
62
60
|
},
|
63
61
|
method: 'GET'
|
64
62
|
}).then((resbody) => {
|
65
|
-
winston.debug("(
|
63
|
+
winston.debug("(ChatbotService) forking public chatbot " + resbody.data.name);
|
66
64
|
let chatbot = resbody.data;
|
67
65
|
return chatbot
|
68
66
|
}).catch((err) => {
|
69
|
-
winston.error('(
|
67
|
+
winston.error('(ChatbotService) FAQ_KB CHATBOT TEMPLATES ERROR ' + err);
|
70
68
|
return err;
|
71
69
|
})
|
72
70
|
}
|
@@ -75,7 +73,7 @@ class ChatbotService {
|
|
75
73
|
|
76
74
|
async createBot(api_url, token, chatbot, project_id) {
|
77
75
|
|
78
|
-
winston.debug("(
|
76
|
+
winston.debug("(ChatbotService) createBot");
|
79
77
|
|
80
78
|
return await axios({
|
81
79
|
url: api_url + '/' + project_id + '/faq_kb/',
|
@@ -86,10 +84,10 @@ class ChatbotService {
|
|
86
84
|
data: chatbot,
|
87
85
|
method: 'POST'
|
88
86
|
}).then((resbody) => {
|
89
|
-
winston.debug("(
|
87
|
+
winston.debug("(ChatbotService) createBot resbody: ", resbody.data);
|
90
88
|
return resbody.data;
|
91
89
|
}).catch((err) => {
|
92
|
-
winston.error("(
|
90
|
+
winston.error("(ChatbotService) CREATE NEW CHATBOT ERROR " + err);
|
93
91
|
return err;
|
94
92
|
})
|
95
93
|
|
@@ -97,7 +95,7 @@ class ChatbotService {
|
|
97
95
|
|
98
96
|
async importFaqs(api_url, id_faq_kb, token, chatbot, project_id) {
|
99
97
|
|
100
|
-
winston.debug("
|
98
|
+
winston.debug("(ChatbotService) importFaqs");
|
101
99
|
|
102
100
|
return await axios({
|
103
101
|
url: api_url + '/' + project_id + '/faq_kb/importjson/' + id_faq_kb + "?intentsOnly=true",
|
@@ -108,14 +106,22 @@ class ChatbotService {
|
|
108
106
|
data: chatbot,
|
109
107
|
method: 'POST'
|
110
108
|
}).then((resbody) => {
|
111
|
-
winston.debug("(
|
109
|
+
winston.debug("(ChatbotService) importFaqs resbody: ", resbody.data);
|
112
110
|
return resbody.data;
|
113
111
|
}).catch((err) => {
|
114
|
-
winston.error("(
|
112
|
+
winston.error("(ChatbotService) IMPORT FAQS ERROR " + err);
|
115
113
|
return err;
|
116
114
|
})
|
117
115
|
}
|
118
116
|
|
117
|
+
async setModified(chatbot_id, modified) {
|
118
|
+
return Faq_kb.findByIdAndUpdate(chatbot_id, { modified: modified }).then((faqKb) => {
|
119
|
+
winston.debug("(ChatbotService) set chatbot to modified response: ", faqKb);
|
120
|
+
return true;
|
121
|
+
}).catch((err) => {
|
122
|
+
return Promise.reject(err);
|
123
|
+
});
|
124
|
+
}
|
119
125
|
}
|
120
126
|
|
121
127
|
module.exports = { ChatbotService }
|