@tiledesk/tiledesk-server 2.3.53 → 2.3.55

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
@@ -1,9 +1,19 @@
1
1
 
2
2
 
3
- 💥 TILEDESK SERVER v2.3.51 💥
3
+ 💥 TILEDESK SERVER v2.3.55 💥
4
4
  🚀 TAGGED AND PUBLISHED ON NPM 🚀
5
5
  🚀 IN PRODUCTION 🚀
6
- (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.51)
6
+ (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.55)
7
+
8
+ # 2.3.55 -> PROD
9
+ - Tybot updated to 0.1.28
10
+
11
+ # 2.3.54
12
+ - Added HIDE_CLOSE_REQUEST_ERRORS env variable
13
+ - Added email.send trigger action
14
+ - Added participants parameter for trigger action
15
+ - Added status -1 for department model to hide department for dashboard and widget. It can be used for chatbot
16
+ - Added template engine to send email trigger action
7
17
 
8
18
  # 2.3.51
9
19
  - Added message.received as trigger event
@@ -19,7 +29,7 @@
19
29
  - Updated widget.json file
20
30
  - Fixed template for: beenInvitedNewUser.html beenInvitedExistingUser.html
21
31
 
22
- # 2.3.49 -> PROD
32
+ # 2.3.49
23
33
  - @tiledesk/tiledesk-tybot-connector": "^0.1.22
24
34
 
25
35
  # 2.3.48
package/app.js CHANGED
@@ -172,6 +172,7 @@ var IPFilter = require('./middleware/ipFilter');
172
172
 
173
173
  // job_here
174
174
  var BanUserNotifier = require('./services/banUserNotifier');
175
+ const { ChatbotService } = require('./services/chatbotService');
175
176
  BanUserNotifier.listen();
176
177
 
177
178
  var modulesManager = undefined;
@@ -207,6 +208,8 @@ var app = express();
207
208
  app.set('views', path.join(__dirname, 'views'));
208
209
  app.set('view engine', 'jade');
209
210
 
211
+ app.set('chatbot_service', new ChatbotService())
212
+
210
213
 
211
214
  // TODO DELETE IT IN THE NEXT RELEASE
212
215
  if (process.env.ENABLE_ALTERNATIVE_CORS_MIDDLEWARE === "true") {
@@ -50,7 +50,7 @@ var DepartmentSchema = new Schema({
50
50
  tags: [TagSchema],
51
51
  status: {
52
52
  type: Number,
53
- default: 1,
53
+ default: 1, // 1: enabled; 0 hidden for widget; -1 hidden for the dashboard;
54
54
  index: true
55
55
  // required: true
56
56
  },
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.3.53",
4
+ "version": "2.3.55",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -42,7 +42,7 @@
42
42
  "@tiledesk/tiledesk-chatbot-util": "^0.8.33",
43
43
  "@tiledesk/tiledesk-json-rules-engine": "^4.0.3",
44
44
  "@tiledesk/tiledesk-rasa-connector": "^1.0.10",
45
- "@tiledesk/tiledesk-tybot-connector": "^0.1.22",
45
+ "@tiledesk/tiledesk-tybot-connector": "^0.1.28",
46
46
  "@tiledesk/tiledesk-dialogflow-connector": "^1.7.4",
47
47
  "app-root-path": "^3.0.0",
48
48
  "bcrypt-nodejs": "0.0.3",
@@ -18,9 +18,11 @@ var leadService = require('../../services/leadService');
18
18
  var LeadConstants = require('../../models/leadConstants');
19
19
  var operatingHoursService = require("../../services/operatingHoursService");
20
20
  var sendMessageUtil = require("../../utils/sendMessageUtil");
21
+ var sendEmailUtil = require("../../utils/sendEmailUtil");
21
22
  var cacheUtil = require("../../utils/cacheUtil");
22
23
  var cacheEnabler = require("../../services/cacheEnabler");
23
24
  var UIDGenerator = require("../../utils/UIDGenerator");
25
+ const RequestConstants = require('../../models/requestConstants');
24
26
 
25
27
 
26
28
  class RulesTrigger {
@@ -201,6 +203,85 @@ class RulesTrigger {
201
203
 
202
204
 
203
205
 
206
+ triggerEventEmitter.on('email.send', function(eventTrigger) {
207
+
208
+ try {
209
+
210
+ winston.debug('runAction eventTrigger.eventSuccess:', eventTrigger.eventSuccess);
211
+ var trigger = eventTrigger.trigger;
212
+ winston.debug('runAction trigger', trigger.toObject());
213
+
214
+
215
+ var action = eventTrigger.action;
216
+ winston.debug('runAction action', action.toObject());
217
+
218
+
219
+ var fullname = action.parameters.fullName || "BOT";
220
+ winston.debug('runAction action fullname: ' + fullname);
221
+
222
+ var subject = action.parameters.fullName || "New Email";
223
+ winston.debug('runAction action subject: ' + subject);
224
+
225
+ var sender = "system";
226
+
227
+ if (action.parameters.sender) {
228
+ sender = action.parameters.sender;
229
+ }
230
+ winston.debug('runAction action sender: ' + sender);
231
+
232
+ var text = action.parameters.text;
233
+ winston.debug('runAction action text: ' + text);
234
+
235
+ var attributes = {};
236
+
237
+ // var attributes = action.parameters.attributes;
238
+ // winston.debug('runAction action attributes: ' + attributes);
239
+
240
+
241
+ var recipient;
242
+ if (eventTrigger.eventKey=="request.create" || eventTrigger.eventKey=="request.participants.join") {
243
+ recipient = eventTrigger.event.request_id;
244
+ }
245
+ if (eventTrigger.eventKey=="message.create.from.requester" || eventTrigger.eventKey=="message.received") {
246
+ recipient = eventTrigger.event.recipient;
247
+ }
248
+ if (eventTrigger.eventKey=="event.emit") {
249
+ winston.debug('runAction action event.emit: ', eventTrigger.event.toObject());
250
+
251
+ //TODO funziona?
252
+ recipient = eventTrigger.event.project_user.id_user;
253
+ }
254
+
255
+ // console.log("eventTrigger.event", eventTrigger.event);
256
+
257
+ winston.debug('runAction action recipient: ' + recipient);
258
+
259
+ var id_project = eventTrigger.event.id_project;
260
+ winston.debug('runAction action id_project: ' + id_project);
261
+
262
+
263
+ var message = eventTrigger.event;
264
+ winston.debug('runAction action message: ', message);
265
+
266
+ if (eventTrigger.event.request && eventTrigger.event.request.lead && eventTrigger.event.request.lead.email) {
267
+ var to = eventTrigger.event.request.lead.email;
268
+ winston.debug('to ' + to);
269
+
270
+ // sendEmailDirect(to, text, project, request_id, subject, tokenQueryString, sourcePage) {
271
+ sendEmailUtil.sendEmailDirect(to, text, id_project, recipient, subject, message);
272
+ } else {
273
+ winston.info('email.send trigger. Lead email is undefined ');
274
+ }
275
+
276
+
277
+ } catch(e) {
278
+ winston.error("Error runAction", e);
279
+ }
280
+
281
+ });
282
+
283
+
284
+
204
285
 
205
286
 
206
287
  triggerEventEmitter.on('request.department.route', function(eventTrigger) {
@@ -683,6 +764,8 @@ class RulesTrigger {
683
764
  var departmentid = action.parameters.departmentid;
684
765
  winston.debug('runAction action departmentid: ' + departmentid);
685
766
 
767
+ var participants = action.parameters.participants;
768
+ winston.debug('runAction action participants: ' + participants);
686
769
  // var attributes = action.parameters.attributes;
687
770
  // winston.debug('runAction action attributes: ' + attributes);
688
771
 
@@ -768,10 +851,24 @@ class RulesTrigger {
768
851
  departmentid = eventAttributes.department;
769
852
  }
770
853
 
854
+
855
+
771
856
  if (eventAttributes.text) {
772
857
  text = eventAttributes.text;
773
858
  }
774
859
 
860
+ // console.log("eventAttributes.participants.length"+ eventAttributes.participants.length);
861
+ if (eventAttributes.participants && eventAttributes.participants.length>0) {
862
+ participants = eventAttributes.participants;
863
+ if (participants[0].indexOf("bot_")>-1) {
864
+ text = "\\start"; //if participants is passed than the bot reply to the first message "welcome" so I changed "welcome" with "\start"
865
+ }
866
+ // status = RequestConstants.ASSIGNED;
867
+ // console.log("eventAttributes.participants",eventAttributes.participants);
868
+ }
869
+
870
+ // console.log("text", text);
871
+
775
872
  if (eventAttributes.status) {
776
873
  status = eventAttributes.status;
777
874
  }
@@ -864,7 +961,7 @@ class RulesTrigger {
864
961
 
865
962
  var new_request = {
866
963
  request_id: request_id, project_user_id: project_user_id, lead_id: createdLead._id, id_project: id_project,
867
- first_text: text, departmentid: departmentid, sourcePage: sourcePage,
964
+ first_text: text, participants: participants, departmentid: departmentid, sourcePage: sourcePage,
868
965
  language: language, userAgent: userAgent, status: status, createdBy: id_user,
869
966
  attributes: attributes, subject: undefined, preflight: preflight, channel: undefined, location: undefined,
870
967
  lead: createdLead, requester: puser
@@ -175,7 +175,7 @@ router.get('/allstatus', [passport.authenticate(['basic', 'jwt'], { session: fal
175
175
 
176
176
  winston.debug("## GET ALL DEPTS req.project ", req.project)
177
177
 
178
- var query = { "id_project": req.projectid };
178
+ var query = { "id_project": req.projectid, status: { $gte: 0 } }; // nascondi quelli con status = hidden (-1) for dashboard
179
179
  //secondo me qui manca un parentesi tonda per gli or
180
180
  if (req.project && req.project.profile && (req.project.profile.type === 'free' && req.project.trialExpired === true) || (req.project.profile.type === 'payment' && req.project.isActiveSubscription === false)) {
181
181
 
package/routes/faq.js CHANGED
@@ -189,7 +189,7 @@ router.put('/:faqid', function (req, res) {
189
189
  update.enabled = req.body.enabled;
190
190
  }
191
191
  if (req.body.reply!=undefined) {
192
- update.reply = req.body.enabled;
192
+ update.reply = req.body.reply;
193
193
  }
194
194
  if (req.body.form!=undefined) {
195
195
  update.form = req.body.form;
package/routes/faq_kb.js CHANGED
@@ -11,6 +11,9 @@ var httpUtil = require("../utils/httpUtil");
11
11
  const { forEach } = require('lodash');
12
12
  var multer = require('multer')
13
13
  var upload = multer()
14
+ var configGlobal = require('../config/global');
15
+
16
+ var chatbot_templates_api_url = "https://chatbot-templates.herokuapp.com/chatbots/public/templates"
14
17
 
15
18
 
16
19
  router.post('/', function (req, res) {
@@ -339,55 +342,129 @@ router.get('/', function (req, res) {
339
342
 
340
343
  });
341
344
 
345
+ router.post('/fork/:id_faq_kb', async (req, res) => {
346
+
347
+ let id_faq_kb = req.params.id_faq_kb;
348
+ winston.info('id_faq_kb: ' + id_faq_kb);
349
+
350
+ const api_url = process.env.API_URL || configGlobal.apiUrl;
351
+ winston.info("fork --> base_url: " + api_url); // check if correct
352
+
353
+ let current_project_id = req.projectid;
354
+ winston.info("current project id: " + current_project_id);
355
+
356
+ let landing_project_id = req.query.projectid;
357
+ winston.info("landing project id " + landing_project_id)
358
+
359
+ let new_bot_name = req.query.name;
360
+ winston.info("new bot name: " + new_bot_name);
361
+
362
+ let public = req.query.public;
363
+ winston.info("public " + public);
364
+
365
+ let token = req.headers.authorization;
366
+
367
+ let cs = req.app.get('chatbot_service')
368
+
369
+ let chatbot = await cs.getBotById(id_faq_kb, public, api_url, chatbot_templates_api_url, token, current_project_id);
370
+ winston.debug("chatbot: ", chatbot)
371
+
372
+ if (!chatbot) {
373
+ return res.status(500).send({ success: false, message: "Unable to get chatbot" });
374
+ }
375
+
376
+ //chatbot.name = new_bot_name;
377
+
378
+ let savedChatbot = await cs.createBot(api_url, token, chatbot, landing_project_id);
379
+ winston.info("savedChatbot: ", savedChatbot)
380
+
381
+ if (!savedChatbot) {
382
+ return res.status(500).send({ success: false, message: "Unable to create new chatbot" });
383
+ }
384
+
385
+ let import_result = await cs.importFaqs(api_url, savedChatbot._id, token, chatbot, landing_project_id);
386
+ winston.info("imported: ", import_result);
387
+
388
+ if (import_result.success == "false") {
389
+ return res.status(500).send({ success: false, message: "Unable to import intents in the new chatbot" });
390
+ }
391
+
392
+ return res.status(200).send({ message: "Chatbot forked successfully", bot_id: savedChatbot._id });
393
+
394
+ })
395
+
396
+
342
397
  router.post('/importjson/:id_faq_kb', upload.single('uploadFile'), (req, res) => {
343
398
 
344
399
  let id_faq_kb = req.params.id_faq_kb;
345
400
  winston.debug('id_faq_kb: ', id_faq_kb);
346
401
 
347
- let json_string = req.file.buffer.toString('utf-8');
348
- winston.debug("json_string: ", json_string);
402
+ let json_string;
403
+ let json;
404
+ if (req.file) {
405
+ json_string = req.file.buffer.toString('utf-8');
406
+ json = JSON.parse(json_string);
407
+ } else {
408
+ json = req.body;
409
+ }
410
+
411
+ winston.info("json_string: " + json_string);
349
412
 
350
413
  if (req.query.intentsOnly == "true") {
351
414
 
352
415
  winston.info("intents only")
353
416
 
354
- const json = JSON.parse(json_string)
355
- console.log("\n intents --> \n")
356
- console.log(json)
357
-
358
417
  json.intents.forEach((intent) => {
359
418
 
360
- var new_faq = new Faq({
419
+ let new_faq = {
361
420
  id_faq_kb: id_faq_kb,
362
421
  id_project: req.projectid,
363
422
  createdBy: req.user.id,
423
+ intent_display_name: intent.intent_display_name,
364
424
  question: intent.question,
365
425
  answer: intent.answer,
366
426
  reply: intent.reply,
367
427
  form: intent.form,
368
428
  enabled: intent.enabled,
369
429
  webhook_enabled: intent.webhook_enabled,
370
- language: intent.language,
371
-
372
- })
430
+ language: intent.language
431
+ }
373
432
 
374
- new_faq.save((err, savedFaq) => {
375
- if (err) {
376
- winston.error("GET FAQ-KB ERROR", err);
377
- if (err.code == 11000) {
378
- return res.status(409).send({ success: false, msg: 'Duplicate intent_display_name.' });
433
+ // overwrite duplicated intents
434
+ if (req.query.overwrite == "true") {
435
+ Faq.findOneAndUpdate({ id_faq_kb: id_faq_kb, intent_display_name: intent.intent_display_name }, new_faq, { new: true, upsert: true, rawResult: true }, (err, savingResult) => {
436
+ if (err) {
437
+ winston.error("findOneAndUpdate (upsert) FAQ ERROR ", err);
379
438
  } else {
380
- winston.debug('--- > ERROR ', err)
381
- return res.status(500).send({ success: false, msg: 'Error saving intent.' });
439
+ if (savingResult.lastErrorObject.updatedExisting == true) {
440
+ winston.info("updated existing intent")
441
+ faqBotEvent.emit('faq.update', savingResult.value);
442
+ } else {
443
+ winston.info("new intent crated")
444
+ faqBotEvent.emit('faq.create', savingResult.value);
445
+ }
382
446
  }
383
- }
384
- winston.debug("NEW FAQ CREATED WITH ID: ", savedFaq._id);
385
- faqBotEvent.emit('faq.create', savedFaq);
386
- })
447
+ })
448
+
449
+ // don't overwrite duplicated intents
450
+ } else {
451
+ Faq.create(new_faq, (err, savedFaq) => {
452
+ if (err) {
453
+ winston.debug("create new FAQ ERROR ", err);
454
+ if (err.code == 11000) {
455
+ winston.error("Duplicate intent_display_name.");
456
+ winston.info("Skip duplicated intent_display_name");
457
+ } else {
458
+ winston.info("new intent crated")
459
+ faqBotEvent.emit('faq.create', savedFaq);
460
+ }
461
+ }
462
+ })
463
+ }
387
464
 
388
465
  })
389
466
 
390
- return res.status(200).send({ success: true, msg: "Intents imported successfully"})
467
+ return res.status(200).send({ success: true, msg: "Intents imported successfully" })
391
468
 
392
469
  } else {
393
470
 
@@ -427,33 +504,54 @@ router.post('/importjson/:id_faq_kb', upload.single('uploadFile'), (req, res) =>
427
504
 
428
505
  json.intents.forEach((intent) => {
429
506
 
430
- var new_faq = new Faq({
507
+ let new_faq = {
431
508
  id_faq_kb: updatedFaq_kb._id,
432
509
  id_project: req.projectid,
433
510
  createdBy: req.user.id,
511
+ intent_display_name: intent.intent_display_name,
434
512
  question: intent.question,
435
513
  answer: intent.answer,
436
514
  reply: intent.reply,
437
515
  form: intent.form,
438
516
  enabled: intent.enabled,
439
517
  webhook_enabled: intent.webhook_enabled,
440
- language: intent.language,
441
-
442
- })
518
+ language: intent.language
519
+ }
443
520
 
444
- new_faq.save((err, savedFaq) => {
445
- if (err) {
446
- winston.error("GET FAQ-KB ERROR", err);
447
- if (err.code == 11000) {
448
- return res.status(409).send({ success: false, msg: 'Duplicate intent_display_name.' });
521
+ // overwrite duplicated intents
522
+ if (req.query.overwrite == "true") {
523
+ Faq.findOneAndUpdate({ id_faq_kb: id_faq_kb, intent_display_name: intent.intent_display_name }, new_faq, { new: true, upsert: true, rawResult: true }, (err, savingResult) => {
524
+ if (err) {
525
+ winston.error("findOneAndUpdate (upsert) FAQ ERROR ", err);
449
526
  } else {
450
- winston.debug('--- > ERROR ', err)
451
- return res.status(500).send({ success: false, msg: 'Error saving intent.' });
527
+
528
+ if (savingResult.lastErrorObject.updatedExisting == true) {
529
+ winston.info("updated existing intent")
530
+ faqBotEvent.emit('faq.update', savingResult.value);
531
+ } else {
532
+ winston.info("new intent crated")
533
+ faqBotEvent.emit('faq.create', savingResult.value);
534
+ }
535
+
452
536
  }
453
- }
454
- winston.debug("NEW FAQ CREATED WITH ID: ", savedFaq._id);
455
- faqBotEvent.emit('faq.create', savedFaq);
456
- })
537
+
538
+ })
539
+
540
+ // don't overwrite duplicated intents
541
+ } else {
542
+ Faq.create(new_faq, (err, savedFaq) => {
543
+ if (err) {
544
+ winston.debug("create new FAQ ERROR ", err);
545
+ if (err.code == 11000) {
546
+ winston.error("Duplicate intent_display_name.");
547
+ winston.info("Skip duplicated intent_display_name");
548
+ } else {
549
+ winston.info("new intent crated")
550
+ faqBotEvent.emit('faq.create', savedFaq);
551
+ }
552
+ }
553
+ })
554
+ }
457
555
 
458
556
  })
459
557
 
@@ -499,12 +597,16 @@ router.get('/exportjson/:id_faq_kb', (req, res) => {
499
597
  intents: intents
500
598
  }
501
599
  let intents_string = JSON.stringify(intents_obj);
502
- res.set({ "Content-Disposition": "attachment; filename=\"intents.txt\"" });
600
+ res.set({ "Content-Disposition": "attachment; filename=\"intents.json\"" });
503
601
  return res.send(intents_string);
504
602
 
505
603
  } else {
604
+
605
+ // if (req.query.file == "false") {
606
+ // return res.status(200).send(json);
607
+ // }
506
608
  let json_string = JSON.stringify(json);
507
- res.set({ "Content-Disposition": "attachment; filename=\"bot.txt\"" });
609
+ res.set({ "Content-Disposition": "attachment; filename=\"bot.json\"" });
508
610
  return res.send(json_string);
509
611
  }
510
612
 
package/routes/request.js CHANGED
@@ -67,7 +67,7 @@ async (req, res) => {
67
67
  let messageStatus = req.body.status || MessageConstants.CHAT_MESSAGE_STATUS.SENDING;
68
68
  winston.debug('messageStatus: ' + messageStatus);
69
69
 
70
- var request_id = req.params.request_id || 'support-group-' + req.projectid + "-" + UIDGenerator.generate();
70
+ var request_id = req.body.request_id || 'support-group-' + req.projectid + "-" + UIDGenerator.generate();
71
71
  winston.debug('request_id: ' + request_id);
72
72
 
73
73
  if (sender) {
@@ -0,0 +1,101 @@
1
+ const axios = require("axios").default;
2
+ const winston = require('../config/winston');
3
+ var Faq_kb = require("../models/faq_kb");
4
+
5
+ class ChatbotService {
6
+
7
+ constructor() {
8
+
9
+ }
10
+
11
+
12
+ async getBotById(id_faq_kb, published, api_url, chatbot_templates_api_url, token, project_id) {
13
+
14
+ winston.info("[CHATBOT SERVICE] getBotById");
15
+
16
+ // private bot
17
+ if (published == "false") {
18
+
19
+ return await axios({
20
+ url: api_url + "/" + project_id + "/faq_kb/exportjson/" + id_faq_kb,
21
+ headers: {
22
+ 'Content-Type': 'application/json',
23
+ 'Authorization': token
24
+ },
25
+ method: 'GET'
26
+ }).then((resbody) => {
27
+ winston.info("(CHATBOT SERVICE) forking private chatbot " + resbody.data.name)
28
+ let chatbot = resbody.data;
29
+ return chatbot;
30
+ }).catch((err) => {
31
+ winston.error('(CHATBOT SERVICE) FAQ_KB EXPORTJSON ERROR ' + err);
32
+ return err;
33
+ })
34
+
35
+ // public bot
36
+ } else {
37
+
38
+ return await axios({
39
+ url: chatbot_templates_api_url + "/" + id_faq_kb,
40
+ headers: {
41
+ 'Content-Type': 'application/json'
42
+ },
43
+ method: 'GET'
44
+ }).then((resbody) => {
45
+ winston.info("(CHATBOT SERVICE) forking public chatbot " + resbody.data);
46
+ let chatbot = resbody.data;
47
+ return chatbot
48
+ }).catch((err) => {
49
+ winston.error('(CHATBOT SERVICE) FAQ_KB CHATBOT TEMPLATES ERROR ' + err);
50
+ return err;
51
+ })
52
+ }
53
+
54
+ }
55
+
56
+ async createBot(api_url, token, chatbot, project_id) {
57
+
58
+ winston.info("[CHATBOT SERVICE] createBot");
59
+
60
+ return await axios({
61
+ url: api_url + '/' + project_id + '/faq_kb/',
62
+ headers: {
63
+ 'Content-Type': 'application/json',
64
+ 'Authorization': token
65
+ },
66
+ data: chatbot,
67
+ method: 'POST'
68
+ }).then((resbody) => {
69
+ winston.debug("(CHATBOT SERVICE) createBot resbody: ", resbody.data);
70
+ return resbody.data;
71
+ }).catch((err) => {
72
+ winston.error("(CHATBOT SERVICE) CREATE NEW CHATBOT ERROR " + err);
73
+ return err;
74
+ })
75
+
76
+ }
77
+
78
+ async importFaqs(api_url, id_faq_kb, token, chatbot, project_id) {
79
+
80
+ winston.info("[CHATBOT SERVICE] importFaqs");
81
+
82
+ return await axios({
83
+ url: api_url + '/' + project_id + '/faq_kb/importjson/' + id_faq_kb + "?intentsOnly=true",
84
+ headers: {
85
+ 'Content-Type': 'application/json',
86
+ 'Authorization': token
87
+ },
88
+ data: chatbot,
89
+ method: 'POST'
90
+ }).then((resbody) => {
91
+ winston.debug("(CHATBOT SERVICE) importFaqs resbody: ", resbody.data);
92
+ return resbody.data;
93
+ }).catch((err) => {
94
+ winston.error("(CHATBOT SERVICE) IMPORT FAQS ERROR " + err);
95
+ return err;
96
+ })
97
+ }
98
+
99
+ }
100
+
101
+ module.exports = { ChatbotService }