@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 CHANGED
@@ -5,6 +5,15 @@
5
5
  🚀 IN PRODUCTION 🚀
6
6
  (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
7
7
 
8
+ # 2.10.68
9
+ - Updated tybot-connector to 0.4.2
10
+
11
+ # 2.10.67
12
+ - Added route for webhooks
13
+ - Added endpoint to run webhook
14
+ - Added chatbot subtypes
15
+ - Updated tybot-connector to 0.4.0
16
+
8
17
  # 2.10.66
9
18
  - Updated QuoteService with new plans
10
19
 
package/app.js CHANGED
@@ -144,6 +144,8 @@ var email = require('./routes/email');
144
144
  var property = require('./routes/property');
145
145
  var segment = require('./routes/segment');
146
146
  var webhook = require('./routes/webhook');
147
+ var webhooks = require('./routes/webhooks');
148
+ var copilot = require('./routes/copilot');
147
149
 
148
150
  var bootDataLoader = require('./services/bootDataLoader');
149
151
  var settingDataLoader = require('./services/settingDataLoader');
@@ -612,7 +614,8 @@ app.use('/:projectid/kb', [passport.authenticate(['basic', 'jwt'], { session: fa
612
614
 
613
615
  app.use('/:projectid/logs', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], logs);
614
616
 
615
-
617
+ app.use('/:projectid/webhooks', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], webhooks);
618
+ app.use('/:projectid/copilot', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], copilot);
616
619
 
617
620
 
618
621
  if (pubModulesManager) {
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ CHATBOT: 'chatbot',
3
+ WEBHOOK: 'webhook',
4
+ COPILOT: 'copilot',
5
+ VOICE: 'voice'
6
+ }
package/models/faq_kb.js CHANGED
@@ -43,6 +43,13 @@ var Faq_kbSchema = new Schema({
43
43
  default: 'internal',
44
44
  index: true
45
45
  },
46
+ subtype: {
47
+ type: String,
48
+ default: function() {
49
+ return this.type === 'tilebot' ? 'chatbot' : undefined;
50
+ },
51
+ index: true
52
+ },
46
53
  // external: {
47
54
  // type: Boolean,
48
55
  // default: false
@@ -0,0 +1,46 @@
1
+ const mongoose = require('mongoose');
2
+ const { customAlphabet } = require('nanoid');
3
+ const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 32);
4
+
5
+ const WebhookSchema = mongoose.Schema({
6
+ webhook_id: {
7
+ type: String,
8
+ default: () => nanoid(),
9
+ unique: true,
10
+ required: true
11
+ },
12
+ id_project: {
13
+ type: String,
14
+ required: true
15
+ },
16
+ chatbot_id: {
17
+ type: String,
18
+ required: true
19
+ },
20
+ block_id: {
21
+ type: String,
22
+ required: true,
23
+ },
24
+ async: {
25
+ type: Boolean,
26
+ required: true,
27
+ default: true
28
+ },
29
+ copilot: {
30
+ type: Boolean,
31
+ required: false
32
+ }
33
+ }, {
34
+ timestamps: true
35
+ })
36
+
37
+ WebhookSchema.index({ id_project: 1, chatbot_id: 1}, { unique: true })
38
+
39
+ const Webhook = mongoose.model("Webhook", WebhookSchema);
40
+
41
+ if (process.env.MONGOOSE_SYNCINDEX) {
42
+ Webhook.syncIndexes();
43
+ winston.verbose("Webhook syncIndexes");
44
+ }
45
+
46
+ module.exports = { Webhook };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-server",
3
3
  "description": "The Tiledesk server module",
4
- "version": "2.10.66",
4
+ "version": "2.10.68",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -47,7 +47,7 @@
47
47
  "@tiledesk/tiledesk-messenger-connector": "^0.1.23",
48
48
  "@tiledesk/tiledesk-rasa-connector": "^1.0.10",
49
49
  "@tiledesk/tiledesk-telegram-connector": "^0.1.14",
50
- "@tiledesk/tiledesk-tybot-connector": "^0.3.4",
50
+ "@tiledesk/tiledesk-tybot-connector": "^0.4.2",
51
51
  "@tiledesk/tiledesk-whatsapp-connector": "^0.1.81",
52
52
  "@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.11",
53
53
  "@tiledesk/tiledesk-sms-connector": "^0.1.11",
@@ -5,6 +5,7 @@ var projectEvent = require('../../event/projectEvent');
5
5
  var winston = require('../../config/winston');
6
6
 
7
7
  var rulesTrigger = require('./rulesTrigger');
8
+ const chatbotTypeConstants = require('../../models/chatbotTypes');
8
9
 
9
10
 
10
11
  function saveTrigger(trigger) {
@@ -20,7 +21,7 @@ projectEvent.on('project.create', async (project) => {
20
21
 
21
22
 
22
23
 
23
- var botIdentity = await faqService.create("Bot", undefined, project._id, "system", "identity", "An identity bot");
24
+ var botIdentity = await faqService.create("Bot", undefined, project._id, "system", "identity", chatbotTypeConstants.CHATBOT, "An identity bot");
24
25
  var botIdentityId = "bot_"+botIdentity.id;
25
26
  winston.debug("botIdentityId:"+botIdentityId);
26
27
 
@@ -0,0 +1,80 @@
1
+ let express = require('express');
2
+ let router = express.Router();
3
+ let winston = require('../config/winston');
4
+ const { Webhook } = require('../models/webhook');
5
+ const webhookService = require('../services/webhookService');
6
+
7
+ router.get('/', async (req, res) => {
8
+
9
+ let id_project = req.projectid;
10
+ let payload = req.body;
11
+ let params = req.query;
12
+ let request_id = req.query.request_id;
13
+ if (!request_id) {
14
+ return res.status(400).send({ success: false, error: "Missing query params request_id" })
15
+ }
16
+ payload.request_id = request_id;
17
+ payload.webhook_query_params = params;
18
+
19
+ let webhooks = await Webhook.find({ id_project: id_project, copilot: true }).catch((err) => {
20
+ winston.error("Error finding copilot webhooks: ", err);
21
+ return res.status(500).send({ success: false, error: err });
22
+ })
23
+
24
+ let promises = webhooks.map((w) =>
25
+ webhookService.run(w, payload)
26
+ .then((response) => {
27
+ return response;
28
+ }).catch((err) => {
29
+ winston.error("Error running webhook: ", err);
30
+ return;
31
+ })
32
+ )
33
+
34
+ Promise.all(promises).then((result) => {
35
+ return res.status(200).send(result);
36
+ }).catch((err) => {
37
+ // Should never executed - check it
38
+ return res.status(500).send({ success: false, error: err });
39
+ })
40
+
41
+ })
42
+
43
+ router.post('/', async (req, res) => {
44
+
45
+ let id_project = req.projectid;
46
+ let payload = req.body;
47
+ let params = req.query;
48
+ let request_id = req.query.request_id;
49
+ if (!request_id) {
50
+ return res.status(400).send({ success: false, error: "Missing query params request_id" })
51
+ }
52
+ payload.request_id = request_id;
53
+ payload.webhook_query_params = params;
54
+
55
+ let webhooks = await Webhook.find({ id_project: id_project, copilot: true }).catch((err) => {
56
+ winston.error("Error finding copilot webhooks: ", err);
57
+ return res.status(500).send({ success: false, error: err });
58
+ })
59
+
60
+ let promises = webhooks.map((w) =>
61
+ webhookService.run(w, payload)
62
+ .then((response) => {
63
+ return response;
64
+ }).catch((err) => {
65
+ winston.error("Error running webhook: ", err);
66
+ return;
67
+ })
68
+ )
69
+
70
+ Promise.all(promises).then((result) => {
71
+ return res.status(200).send(result);
72
+ }).catch((err) => {
73
+ // Should never executed - check it
74
+ return res.status(500).send({ success: false, error: err });
75
+ })
76
+
77
+ })
78
+
79
+
80
+ module.exports = router;
package/routes/faq_kb.js CHANGED
@@ -50,7 +50,7 @@ router.post('/', roleChecker.hasRole('admin'), async function (req, res) {
50
50
  //return res.status(403).send({ success: false, error: "Maximum number of chatbots reached for the current plan", plan_limit: chatbots_limit })
51
51
  }
52
52
 
53
- faqService.create(req.body.name, req.body.url, req.projectid, req.user.id, req.body.type, req.body.description, req.body.webhook_url, req.body.webhook_enabled, req.body.language, req.body.template, req.body.mainCategory, req.body.intentsEngine, req.body.attributes).then(function (savedFaq_kb) {
53
+ faqService.create(req.body.name, req.body.url, req.projectid, req.user.id, req.body.type, req.body.subtype, req.body.description, req.body.webhook_url, req.body.webhook_enabled, req.body.language, req.body.template, req.body.mainCategory, req.body.intentsEngine, req.body.attributes).then(function (savedFaq_kb) {
54
54
  res.json(savedFaq_kb);
55
55
  });
56
56
 
@@ -683,7 +683,7 @@ router.post('/importjson/:id_faq_kb', roleChecker.hasRole('admin'), upload.singl
683
683
  // **** CREATE TRUE option ****
684
684
  // ****************************
685
685
  if (req.query.create === 'true') {
686
- let savedChatbot = await faqService.create(json.name, undefined, req.projectid, req.user.id, "tilebot", json.description, json.webhook_url, json.webhook_enabled, json.language, undefined, undefined, undefined, json.attributes)
686
+ let savedChatbot = await faqService.create(json.name, undefined, req.projectid, req.user.id, "tilebot", json.subtype, json.description, json.webhook_url, json.webhook_enabled, json.language, undefined, undefined, undefined, json.attributes)
687
687
  .catch((err) => {
688
688
  winston.error("Error creating new chatbot")
689
689
  return res.status(400).send({ succes: false, message: "Error creatings new chatbot", error: err })
@@ -932,6 +932,7 @@ router.get('/exportjson/:id_faq_kb', roleChecker.hasRole('admin'), (req, res) =>
932
932
  language: faq_kb.language,
933
933
  name: faq_kb.name,
934
934
  type: faq_kb.type,
935
+ subtype: faq_kb.subtype,
935
936
  description: faq_kb.description,
936
937
  attributes: faq_kb.attributes,
937
938
  intents: intents
package/routes/webhook.js CHANGED
@@ -1,10 +1,23 @@
1
1
  var express = require('express');
2
2
  var router = express.Router();
3
+ const uuidv4 = require('uuid/v4');
3
4
  var { KB, Namespace } = require('../models/kb_setting');
4
5
  var winston = require('../config/winston');
5
6
  const JobManager = require('../utils/jobs-worker-queue-manager/JobManagerV2');
6
7
  const { Scheduler } = require('../services/Scheduler');
7
8
  const { AiReindexService } = require('../services/aiReindexService');
9
+ const { Webhook } = require('../models/webhook');
10
+ const httpUtil = require('../utils/httpUtil');
11
+ var jwt = require('jsonwebtoken');
12
+ const Faq_kb = require('../models/faq_kb');
13
+ const webhookService = require('../services/webhookService');
14
+
15
+ const port = process.env.PORT || '3000';
16
+ let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/";;
17
+ if (process.env.TILEBOT_ENDPOINT) {
18
+ TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/"
19
+ }
20
+ winston.debug("TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
8
21
 
9
22
  const KB_WEBHOOK_TOKEN = process.env.KB_WEBHOOK_TOKEN || 'kbcustomtoken';
10
23
  const AMQP_MANAGER_URL = process.env.AMQP_MANAGER_URL;
@@ -167,6 +180,63 @@ router.post('/kb/status', async (req, res) => {
167
180
 
168
181
  })
169
182
 
183
+ router.all('/:webhook_id', async (req, res) => {
184
+
185
+ let webhook_id = req.params.webhook_id;
186
+ let payload = req.body;
187
+ payload.webhook_http_method = req.method;
188
+ let params = req.query;
189
+ if (params) {
190
+ payload.webhook_query_params = params;
191
+ }
192
+
193
+ let webhook = await Webhook.findOne({ webhook_id: webhook_id }).catch((err) => {
194
+ winston.error("Error finding webhook: ", err);
195
+ return res.status(500).send({ success: false, error: err });
196
+ })
197
+
198
+ if (!webhook) {
199
+ winston.warn("Webhook not found with id " + webhook_id);
200
+ return res.status(404).send({ success: false, error: "Webhook not found with id " + webhook_id });
201
+ }
202
+
203
+ webhookService.run(webhook, payload).then((response) => {
204
+ return res.status(200).send(response);
205
+ }).catch((err) => {
206
+ let status = err.status || 500;
207
+ return res.status(status).send(err.data);
208
+ })
209
+
210
+ // let chatbot = await Faq_kb.findById(webhook.chatbot_id).select("+secret").catch((err) => {
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
+ // })
214
+
215
+ // if (!chatbot) {
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
+ // }
219
+
220
+ // let token = await generateChatbotToken(chatbot);
221
+
222
+ // let url = TILEBOT_ENDPOINT + 'block/' + webhook.id_project + "/" + webhook.chatbot_id + "/" + webhook.block_id;
223
+ // winston.info("Webhook chatbot URL: ", url);
224
+
225
+ // payload.async = webhook.async;
226
+ // payload.token = token;
227
+
228
+ // if (process.env.NODE_ENV === 'test') {
229
+ // return res.status(200).send({ success: true, message: "Webhook disabled in test mode"})
230
+ // }
231
+
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
+ })
239
+
170
240
  async function scheduleScrape(resources) {
171
241
 
172
242
  let scheduler = new Scheduler({ jobManager: jobManager });
@@ -185,4 +255,19 @@ async function scheduleScrape(resources) {
185
255
  return true;
186
256
  }
187
257
 
258
+ async function generateChatbotToken(chatbot) {
259
+ let signOptions = {
260
+ issuer: 'https://tiledesk.com',
261
+ subject: 'bot',
262
+ audience: 'https://tiledesk.com/bots/' + chatbot._id,
263
+ jwtid: uuidv4()
264
+ };
265
+
266
+ let botPayload = chatbot.toObject();
267
+ let botSecret = botPayload.secret;
268
+
269
+ var bot_token = jwt.sign(botPayload, botSecret, signOptions);
270
+ return bot_token;
271
+ }
272
+
188
273
  module.exports = router;
@@ -0,0 +1,156 @@
1
+ var express = require('express');
2
+ var router = express.Router();
3
+ var winston = require('../config/winston');
4
+ const { Webhook } = require('../models/webhook');
5
+ const httpUtil = require('../utils/httpUtil');
6
+ const { customAlphabet } = require('nanoid');
7
+ const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 32);
8
+
9
+ // const port = process.env.PORT || '3000';
10
+ // let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/ext/";;
11
+ // if (process.env.TILEBOT_ENDPOINT) {
12
+ // TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/ext/"
13
+ // }
14
+ // winston.debug("TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
15
+
16
+
17
+ router.get('/:chatbot_id/', async (req, res) => {
18
+
19
+ let id_project = req.projectid;
20
+ let chatbot_id = req.params.chatbot_id;
21
+
22
+ let webhook = await Webhook.findOne({ id_project: id_project, chatbot_id: chatbot_id }).catch((err) => {
23
+ winston.error("Error finding webhook: ", err);
24
+ return res.status(500).send({ success: false, error: "Error findin webhook with for chatbot " + chatbot_id });
25
+ })
26
+
27
+ if (!webhook) {
28
+ winston.verbose("Webhook not found for chatbot " + chatbot_id);
29
+ return res.status(404).send({ success: false, error: "Webhook not found for chatbot " + chatbot_id });
30
+ }
31
+
32
+ res.status(200).send(webhook);
33
+
34
+ })
35
+
36
+
37
+ router.post('/', async (req, res) => {
38
+
39
+ let id_project = req.projectid;
40
+
41
+ let webhook = new Webhook({
42
+ id_project: id_project,
43
+ chatbot_id: req.body.chatbot_id || req.body.id_faq_kb,
44
+ block_id: req.body.block_id,
45
+ async: req.body.async
46
+ })
47
+
48
+ webhook.save((err, savedWebhook) => {
49
+ if (err) {
50
+ if (err.code === 11000) {
51
+ winston.verbose("Webhook already exists for chatbot " + chatbot_id);
52
+ return res.status(403).send({ success: false, message: "Webhook already exists for chatbot " + chatbot_id });
53
+ }
54
+ winston.error("Error saving new webhook ", err);
55
+ return res.status(500).send({ success: false, error: err });
56
+ }
57
+
58
+ res.status(200).send(savedWebhook);
59
+ })
60
+
61
+ })
62
+
63
+ // router.post('/webhook_id', async (req, res) => {
64
+
65
+ // let id_project = req.projectid;
66
+ // let webhook_id = req.params.webhook_id;
67
+ // let payload = req.body;
68
+
69
+ // let webhook = await Webhook.findOne({ id_project: id_project, webhook_id: webhook_id }).catch((err) => {
70
+ // winston.error("Error finding webhook: ", err);
71
+ // return res.status(500).send({ success: false, error: err });
72
+ // })
73
+
74
+ // if (!webhook) {
75
+ // winston.warn("Webhook not found with id " + webhook_id);
76
+ // return res.status(404).send({ success: false, error: "Webhook not found with id " + webhook_id });
77
+ // }
78
+
79
+ // let url = TILEBOT_ENDPOINT + 'block/' + id_project + "/" + webhook.chatbot_id + "/" + webhook.block_id;
80
+
81
+ // payload.async = webhook.async;
82
+
83
+ // let response = httpUtil.post(url, payload).catch((err) => {
84
+ // winston.error("Error calling webhook on post: ", err);
85
+ // return res.status(500).send({ success: false, error: err });
86
+ // })
87
+
88
+ // res.status(200).send(response);
89
+
90
+ // })
91
+
92
+ router.put("/:chatbot_id/regenerate", async (req, res) => {
93
+
94
+ let id_project = req.projectid;
95
+ let chatbot_id = req.params.chatbot_id;
96
+
97
+ let update = {
98
+ webhook_id: nanoid()
99
+ }
100
+
101
+ let updatedWebhook = await Webhook.findOneAndUpdate({ id_project: id_project, chatbot_id: chatbot_id }, update, { new: true }).catch((err) => {
102
+ winston.error("Error updating webhook ", err);
103
+ return res.status(500).send({ success: false, error: "Error updating webhook for chatbot " + chatbot_id });
104
+ })
105
+
106
+ if (!updatedWebhook) {
107
+ winston.verbose("Webhook not found for chatbot " + chatbot_id);
108
+ return res.status(404).send({ success: false, error: "Webhook not found for chatbot " + chatbot_id });
109
+ }
110
+
111
+ res.status(200).send(updatedWebhook);
112
+ })
113
+
114
+ router.put("/:chatbot_id", async (req, res) => {
115
+
116
+ let id_project = req.projectid;
117
+ let chatbot_id = req.params.chatbot_id;
118
+
119
+ let update = {};
120
+
121
+ if (req.body.hasOwnProperty("async")) {
122
+ update.async = req.body.async;
123
+ }
124
+
125
+ if (req.body.hasOwnProperty("copilot")) {
126
+ update.copilot = req.body.copilot;
127
+ }
128
+
129
+ let updatedWebhook = await Webhook.findOneAndUpdate({ id_project: id_project, chatbot_id: chatbot_id }, update, { new: true }).catch((err) => {
130
+ winston.error("Error updating webhook ", err);
131
+ return res.status(500).send({ success: false, error: "Error updating webhook for chatbot " + chatbot_id });
132
+ })
133
+
134
+ if (!updatedWebhook) {
135
+ winston.verbose("Webhook not found for chatbot " + chatbot_id);
136
+ return res.status(404).send({ success: false, error: "Webhook not found for chatbot " + chatbot_id });
137
+ }
138
+
139
+ res.status(200).send(updatedWebhook);
140
+ })
141
+
142
+ router.delete("/:chatbot_id", async (req, res) => {
143
+
144
+ let id_project = req.projectid;
145
+ let chatbot_id = req.params.chatbot_id;
146
+
147
+ await Webhook.deleteOne({ id_project: id_project, chatbot_id: chatbot_id }).catch((err) => {
148
+ winston.error("Error deleting webhook ", err);
149
+ return res.status(500).send({ success: false, error: "Error deleting webhook for chatbot " + chatbot_id });
150
+ })
151
+
152
+ res.status(200).send({ success: true, message: "Webhook for chatbot " + chatbot_id + " deleted successfully" });
153
+ })
154
+
155
+
156
+ module.exports = router;
@@ -207,7 +207,6 @@ class QuoteManager {
207
207
  * Get current quote for a single type (tokens or request or ...)
208
208
  */
209
209
  async getCurrentQuote(project, object, type) {
210
-
211
210
  this.project = project;
212
211
  let key = await this.generateKey(object, type);
213
212
  winston.verbose("[QuoteManager] getCurrentQuote key: " + key);