@tiledesk/tiledesk-server 2.10.66 → 2.10.68
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 +9 -0
- package/app.js +4 -1
- package/models/chatbotTypes.js +6 -0
- package/models/faq_kb.js +7 -0
- package/models/webhook.js +46 -0
- package/package.json +2 -2
- package/pubmodules/trigger/start.js +2 -1
- package/routes/copilot.js +80 -0
- package/routes/faq_kb.js +3 -2
- package/routes/webhook.js +85 -0
- package/routes/webhooks.js +156 -0
- package/services/QuoteManager.js +0 -1
- package/services/faqService.js +170 -66
- package/services/webhookService.js +71 -0
- package/test/faqService.js +8 -5
- package/test/kbRoute.js +92 -113
- package/test/quoteManager.js +4 -2
- package/test/requestService.js +4 -3
- package/test/userRequestRoute.js +2 -1
- package/test/webhookRoute.js +376 -0
- package/test-int/bot.js +6 -5
- package/utils/httpUtil.js +51 -19
package/services/faqService.js
CHANGED
@@ -4,12 +4,13 @@ var winston = require('../config/winston');
|
|
4
4
|
const botEvent = require('../event/botEvent');
|
5
5
|
const ActionsConstants = require('../models/actionsConstants');
|
6
6
|
const uuidv4 = require('uuid/v4');
|
7
|
+
const chatbotTypes = require("../models/chatbotTypes");
|
7
8
|
|
8
9
|
|
9
10
|
class FaqService {
|
10
11
|
|
11
12
|
|
12
|
-
create(name, url, projectid, user_id, type, description, webhook_url, webhook_enabled, language, template, mainCategory, intentsEngine, attributes) {
|
13
|
+
create(name, url, projectid, user_id, type, subtype, description, webhook_url, webhook_enabled, language, template, mainCategory, intentsEngine, attributes) {
|
13
14
|
var that = this;
|
14
15
|
return new Promise(function (resolve, reject) {
|
15
16
|
|
@@ -22,6 +23,7 @@ class FaqService {
|
|
22
23
|
webhook_url: webhook_url,
|
23
24
|
webhook_enabled: webhook_enabled,
|
24
25
|
type: type,
|
26
|
+
subtype: subtype,
|
25
27
|
language: language,
|
26
28
|
public: false,
|
27
29
|
certified: false,
|
@@ -47,6 +49,25 @@ class FaqService {
|
|
47
49
|
|
48
50
|
if (type === "internal" || type === "tilebot") {
|
49
51
|
|
52
|
+
if (!subtype) {
|
53
|
+
if (!template) {
|
54
|
+
template = "empty";
|
55
|
+
}
|
56
|
+
} else {
|
57
|
+
|
58
|
+
if (subtype === chatbotTypes.CHATBOT) {
|
59
|
+
if (!template) {
|
60
|
+
template = "empty";
|
61
|
+
}
|
62
|
+
} else if (subtype === chatbotTypes.WEBHOOK) {
|
63
|
+
template = "blank_webhook"
|
64
|
+
} else if (subtype === chatbotTypes.COPILOT) {
|
65
|
+
template = "blank_copilot"
|
66
|
+
} else {
|
67
|
+
template = "empty";
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
50
71
|
if (!template) {
|
51
72
|
template = "empty";
|
52
73
|
}
|
@@ -89,7 +110,6 @@ class FaqService {
|
|
89
110
|
{ 'question': 'Sample Frame', 'answer': 'tdFrame:https://www.emanueleferonato.com/wp-content/uploads/2019/02/runner/\n* What can you do?\n* Back to start tdAction:start', 'topic': 'sample' },
|
90
111
|
{ 'question': 'Sample Video', 'answer': 'tdVideo:https://www.youtube.com/embed/EngW7tLk6R8\n* What can you do?\n* Back to start tdAction:start', 'topic': 'sample' },
|
91
112
|
{ 'question': 'Where are you?', 'answer': 'We are here ❤️\ntdFrame:https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d6087916.923447935!2d8.234804542117423!3d41.836572992140624!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x12d4fe82448dd203%3A0xe22cf55c24635e6f!2sItaly!5e0!3m2!1sen!2sit!4v1613657475377!5m2!1sen!2sit\n* Back to start tdAction:start', 'topic': 'sample' },
|
92
|
-
|
93
113
|
// { 'question': 'Sample Webhook', 'answer': 'tdWebhook:https://tiledesk-bot-webhook.tiledesk.repl.co', 'topic': 'sample' },
|
94
114
|
{ 'question': 'Sample Action', 'answer': 'Hello 👋 Would you like to take a closer look at our offer?\n* Yes, please tdAction:yes_action\n* No tdAction:no_action', 'intent_display_name': 'action1', 'topic': 'sample' },
|
95
115
|
{ 'question': 'Yes Action', 'answer': 'Great! Take a look here:\n* Tiledesk Pricing https://tiledesk.com/pricing-cloud/', 'intent_display_name': 'yes_action', 'topic': 'sample' },
|
@@ -108,76 +128,78 @@ class FaqService {
|
|
108
128
|
// { 'question': '\\start', 'answer': 'Hello', 'intent_display_name': 'start', 'topic': 'internal' },
|
109
129
|
// { 'question': 'defaultFallback', 'answer': 'I can not provide an adequate answer. Write a new question or talk to a human agent.\n* Back to start tdAction:start\n* See the docs https://docs.tiledesk.com/\n* 👨🏻🦰 I want an agent', 'intent_display_name': 'defaultFallback', 'topic': 'internal' }, //TODO se metto spazio n * nn va
|
110
130
|
// ]
|
111
|
-
faqsArray = [
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
"
|
116
|
-
|
131
|
+
faqsArray = [
|
132
|
+
{
|
133
|
+
"webhook_enabled": false,
|
134
|
+
"enabled": true,
|
135
|
+
"actions": [{
|
136
|
+
"_tdActionType": "reply",
|
137
|
+
"text": "I didn't understand. Can you rephrase your question?",
|
138
|
+
"attributes": {
|
139
|
+
"commands": [{
|
140
|
+
"type": "wait",
|
141
|
+
"time": 500
|
142
|
+
}, {
|
143
|
+
"type": "message",
|
144
|
+
"message": {
|
145
|
+
"type": "text",
|
146
|
+
"text": "I didn't understand. Can you rephrase your question?"
|
147
|
+
}
|
148
|
+
}]
|
149
|
+
}
|
150
|
+
}],
|
151
|
+
"intent_display_name": "defaultFallback",
|
117
152
|
"attributes": {
|
118
|
-
"
|
119
|
-
"
|
120
|
-
"
|
121
|
-
}
|
122
|
-
"type": "message",
|
123
|
-
"message": {
|
124
|
-
"type": "text",
|
125
|
-
"text": "I didn't understand. Can you rephrase your question?"
|
126
|
-
}
|
127
|
-
}]
|
153
|
+
"position": {
|
154
|
+
"x": 714,
|
155
|
+
"y": 528
|
156
|
+
}
|
128
157
|
}
|
129
|
-
}
|
130
|
-
|
131
|
-
|
132
|
-
"
|
133
|
-
"
|
134
|
-
"
|
135
|
-
}
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
}],
|
144
|
-
"question": "\\start",
|
145
|
-
"intent_display_name": "start",
|
146
|
-
"attributes": {
|
147
|
-
"position": {
|
148
|
-
"x": 172,
|
149
|
-
"y": 384
|
158
|
+
}, {
|
159
|
+
"webhook_enabled": false,
|
160
|
+
"enabled": true,
|
161
|
+
"actions": [{
|
162
|
+
"_tdActionType": "intent",
|
163
|
+
"intentName": "#" + custom_intent_id
|
164
|
+
}],
|
165
|
+
"question": "\\start",
|
166
|
+
"intent_display_name": "start",
|
167
|
+
"attributes": {
|
168
|
+
"position": {
|
169
|
+
"x": 172,
|
170
|
+
"y": 384
|
171
|
+
}
|
150
172
|
}
|
151
|
-
}
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
173
|
+
}, {
|
174
|
+
"webhook_enabled": false,
|
175
|
+
"enabled": true,
|
176
|
+
"actions": [{
|
177
|
+
"_tdActionType": "reply",
|
178
|
+
"attributes": {
|
179
|
+
"disableInputMessage": false,
|
180
|
+
"commands": [{
|
181
|
+
"type": "wait",
|
182
|
+
"time": 500
|
183
|
+
}, {
|
184
|
+
"type": "message",
|
185
|
+
"message": {
|
186
|
+
"type": "text",
|
187
|
+
"text": "Hi, how can I help you?"
|
188
|
+
}
|
189
|
+
}]
|
190
|
+
},
|
191
|
+
"text": "Hi, how can I help you?\r\n"
|
192
|
+
}],
|
193
|
+
"intent_display_name": "welcome",
|
194
|
+
"intent_id": custom_intent_id,
|
157
195
|
"attributes": {
|
158
|
-
"
|
159
|
-
|
160
|
-
"
|
161
|
-
|
162
|
-
}, {
|
163
|
-
"type": "message",
|
164
|
-
"message": {
|
165
|
-
"type": "text",
|
166
|
-
"text": "Hi, how can I help you?"
|
167
|
-
}
|
168
|
-
}]
|
169
|
-
},
|
170
|
-
"text": "Hi, how can I help you?\r\n"
|
171
|
-
}],
|
172
|
-
"intent_display_name": "welcome",
|
173
|
-
"intent_id": custom_intent_id,
|
174
|
-
"attributes": {
|
175
|
-
"position": {
|
176
|
-
"x": 714,
|
177
|
-
"y": 113
|
196
|
+
"position": {
|
197
|
+
"x": 714,
|
198
|
+
"y": 113
|
199
|
+
}
|
178
200
|
}
|
179
201
|
}
|
180
|
-
|
202
|
+
]
|
181
203
|
|
182
204
|
}
|
183
205
|
|
@@ -196,7 +218,89 @@ class FaqService {
|
|
196
218
|
faqsArray = [];
|
197
219
|
}
|
198
220
|
|
221
|
+
if (template === "blank_webhook") {
|
222
|
+
let custom_intent_id = uuidv4();
|
223
|
+
|
224
|
+
faqsArray = [
|
225
|
+
{
|
226
|
+
"webhook_enabled": false,
|
227
|
+
"enabled": true,
|
228
|
+
"actions": [{
|
229
|
+
"_tdActionType": "intent",
|
230
|
+
"intentName": "#" + custom_intent_id
|
231
|
+
}],
|
232
|
+
"question": "",
|
233
|
+
"intent_display_name": "webhook",
|
234
|
+
"attributes": {
|
235
|
+
"position": {
|
236
|
+
"x": 172,
|
237
|
+
"y": 384
|
238
|
+
}
|
239
|
+
}
|
240
|
+
},
|
241
|
+
{
|
242
|
+
"webhook_enabled": false,
|
243
|
+
"enabled": true,
|
244
|
+
"actions": [{
|
245
|
+
"_tdActionType": "web_response",
|
246
|
+
"status": 200,
|
247
|
+
"bodyType": "json",
|
248
|
+
"payload": '{"success": true , "message": "Your webhook is online!"}'
|
249
|
+
}],
|
250
|
+
"intent_display_name": "response",
|
251
|
+
"intent_id": custom_intent_id,
|
252
|
+
"attributes": {
|
253
|
+
"position": {
|
254
|
+
"x": 714,
|
255
|
+
"y": 113
|
256
|
+
}
|
257
|
+
}
|
258
|
+
}
|
259
|
+
]
|
260
|
+
}
|
261
|
+
|
262
|
+
if (template === "blank_copilot") {
|
263
|
+
let custom_intent_id = uuidv4();
|
264
|
+
|
265
|
+
faqsArray = [
|
266
|
+
{
|
267
|
+
"webhook_enabled": false,
|
268
|
+
"enabled": true,
|
269
|
+
"actions": [{
|
270
|
+
"_tdActionType": "intent",
|
271
|
+
"intentName": "#" + custom_intent_id
|
272
|
+
}],
|
273
|
+
"question": "",
|
274
|
+
"intent_display_name": "webhook",
|
275
|
+
"attributes": {
|
276
|
+
"position": {
|
277
|
+
"x": 172,
|
278
|
+
"y": 384
|
279
|
+
}
|
280
|
+
}
|
281
|
+
},
|
282
|
+
{
|
283
|
+
"webhook_enabled": false,
|
284
|
+
"enabled": true,
|
285
|
+
"actions": [{
|
286
|
+
"_tdActionType": "web_response",
|
287
|
+
"status": 200,
|
288
|
+
"bodyType": "json",
|
289
|
+
"payload": '{"title": "Official Copilot", "text": "This is a suggestion!"}'
|
290
|
+
}],
|
291
|
+
"intent_display_name": "response",
|
292
|
+
"intent_id": custom_intent_id,
|
293
|
+
"attributes": {
|
294
|
+
"position": {
|
295
|
+
"x": 714,
|
296
|
+
"y": 113
|
297
|
+
}
|
298
|
+
}
|
299
|
+
}
|
300
|
+
]
|
301
|
+
}
|
199
302
|
|
303
|
+
|
200
304
|
faqsArray.forEach(faq => {
|
201
305
|
|
202
306
|
var newFaq = new Faq({
|
@@ -0,0 +1,71 @@
|
|
1
|
+
const faq_kb = require("../models/faq_kb");
|
2
|
+
const httpUtil = require("../utils/httpUtil");
|
3
|
+
const uuidv4 = require('uuid/v4');
|
4
|
+
var jwt = require('jsonwebtoken');
|
5
|
+
var winston = require('../config/winston');
|
6
|
+
|
7
|
+
const port = process.env.PORT || '3000';
|
8
|
+
let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/";;
|
9
|
+
if (process.env.TILEBOT_ENDPOINT) {
|
10
|
+
TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/"
|
11
|
+
}
|
12
|
+
winston.debug("TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
|
13
|
+
|
14
|
+
class WebhookService {
|
15
|
+
|
16
|
+
async run(webhook, payload) {
|
17
|
+
|
18
|
+
return new Promise(async (resolve, reject) => {
|
19
|
+
|
20
|
+
winston.verbose("(WebhookService) Run webhook " + webhook.webhook_id);
|
21
|
+
let chatbot = await faq_kb.findById(webhook.chatbot_id).select("+secret").catch((err) => {
|
22
|
+
winston.error("Error finding chatbot ", err);
|
23
|
+
reject(err);
|
24
|
+
})
|
25
|
+
|
26
|
+
if (!chatbot) {
|
27
|
+
winston.verbose("Chatbot not found with id " + webhook.chatbot_id);
|
28
|
+
reject("Chatbot not found with id " + webhook.chatbot_id);
|
29
|
+
}
|
30
|
+
|
31
|
+
let token = await this.generateChatbotToken(chatbot);
|
32
|
+
|
33
|
+
let url = TILEBOT_ENDPOINT + 'block/' + webhook.id_project + "/" + webhook.chatbot_id + "/" + webhook.block_id;
|
34
|
+
winston.info("Webhook chatbot URL: ", url);
|
35
|
+
|
36
|
+
payload.async = webhook.async;
|
37
|
+
payload.token = token;
|
38
|
+
|
39
|
+
if (process.env.NODE_ENV === 'test') {
|
40
|
+
resolve(true);
|
41
|
+
}
|
42
|
+
|
43
|
+
await httpUtil.post(url, payload).then((response) => {
|
44
|
+
resolve(response.data);
|
45
|
+
}).catch((err) => {
|
46
|
+
winston.error("Error calling webhook on post: ", err);
|
47
|
+
reject(err);
|
48
|
+
})
|
49
|
+
|
50
|
+
})
|
51
|
+
}
|
52
|
+
|
53
|
+
async generateChatbotToken(chatbot) {
|
54
|
+
let signOptions = {
|
55
|
+
issuer: 'https://tiledesk.com',
|
56
|
+
subject: 'bot',
|
57
|
+
audience: 'https://tiledesk.com/bots/' + chatbot._id,
|
58
|
+
jwtid: uuidv4()
|
59
|
+
};
|
60
|
+
|
61
|
+
let botPayload = chatbot.toObject();
|
62
|
+
let botSecret = botPayload.secret;
|
63
|
+
|
64
|
+
var bot_token = jwt.sign(botPayload, botSecret, signOptions);
|
65
|
+
return bot_token;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
let webhookService = new WebhookService();
|
70
|
+
|
71
|
+
module.exports = webhookService;
|
package/test/faqService.js
CHANGED
@@ -22,7 +22,7 @@ let log = false;
|
|
22
22
|
|
23
23
|
describe('FaqService()', function () {
|
24
24
|
|
25
|
-
it('
|
25
|
+
it('createee-and-search', (done) => {
|
26
26
|
|
27
27
|
var email = "test-subscription-" + Date.now() + "@email.com";
|
28
28
|
var pwd = "pwd";
|
@@ -40,10 +40,12 @@ describe('FaqService()', function () {
|
|
40
40
|
createdBy: savedUser._id,
|
41
41
|
updatedBy: savedUser._id
|
42
42
|
});
|
43
|
+
|
43
44
|
|
44
45
|
newFaq.save(function (err, savedFaq) {
|
45
46
|
winston.debug("err", err);
|
46
47
|
winston.debug("resolve", savedFaq);
|
48
|
+
|
47
49
|
expect(savedBot.name).to.equal("testbot");
|
48
50
|
expect(savedBot.secret).to.not.equal(null);
|
49
51
|
expect(savedFaq.question).to.equal("question");
|
@@ -51,15 +53,15 @@ describe('FaqService()', function () {
|
|
51
53
|
expect(savedFaq.intent_display_name).to.not.equal(undefined);
|
52
54
|
expect(savedFaq.webhook_enabled).to.equal(false);
|
53
55
|
|
54
|
-
var query = { "
|
56
|
+
var query = { "id_faq_kb": savedBot._id };
|
55
57
|
|
56
58
|
// aggiunta qui
|
57
59
|
query.$text = { "$search": "question" };
|
58
60
|
|
59
61
|
return Faq.find(query, { score: { $meta: "textScore" } })
|
60
62
|
.sort({ score: { $meta: "textScore" } }) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
|
61
|
-
.lean()
|
62
|
-
exec(function (err, faqs) {
|
63
|
+
.lean()
|
64
|
+
.exec(function (err, faqs) {
|
63
65
|
if (log) { console.log("faqs", faqs); }
|
64
66
|
// expect(faqs.length).to.equal(1);
|
65
67
|
expect(faqs[0]._id.toString()).to.equal(savedFaq._id.toString());
|
@@ -106,7 +108,7 @@ describe('FaqService()', function () {
|
|
106
108
|
expect(savedFaq.intent_display_name).to.equal("question1");
|
107
109
|
expect(savedFaq.webhook_enabled).to.equal(false);
|
108
110
|
|
109
|
-
var query = { "
|
111
|
+
var query = { "id_faq_kb": savedBot._id };
|
110
112
|
|
111
113
|
// aggiunta qui
|
112
114
|
query.$text = { "$search": "question" };
|
@@ -115,6 +117,7 @@ describe('FaqService()', function () {
|
|
115
117
|
.sort({ score: { $meta: "textScore" } }) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
|
116
118
|
.lean().
|
117
119
|
exec(function (err, faqs) {
|
120
|
+
if (err) { console.error("err: ", err )}
|
118
121
|
if (log) { console.log("faqs", faqs); }
|
119
122
|
// expect(faqs.length).to.equal(1);
|
120
123
|
expect(faqs[0]._id.toString()).to.equal(savedFaq._id.toString());
|