@tiledesk/tiledesk-tybot-connector 0.1.21 → 0.1.23

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.
Files changed (36) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/ExtApi.js +37 -0
  3. package/index backup.js +656 -0
  4. package/index.js +58 -461
  5. package/models/IntentForm.js +12 -13
  6. package/models/MockBotsDataSource.js +74 -0
  7. package/models/MockIntentsMachine.js +39 -0
  8. package/models/MongodbBotsDataSource.js +73 -0
  9. package/models/MongodbIntentsMachine.js +55 -0
  10. package/models/{TiledeskChatbot_Intents_Adapter.js → TiledeskChatbot backup.js } +0 -1
  11. package/models/TiledeskChatbot.js +206 -180
  12. package/models/TiledeskIntentsMachine.js +90 -0
  13. package/models/faqKbService.js +27 -0
  14. package/models/faqService.js +22 -0
  15. package/models/faq_kb.js +11 -28
  16. package/package.json +2 -2
  17. package/test/close_directive_test.js +49 -0
  18. package/test/directives_test.js +24 -26
  19. package/test/disable_input_text_directive_test.js +88 -0
  20. package/test/mock_query_test.js +276 -0
  21. package/test/single_test.sh +4 -0
  22. package/test/when_open_directive_test.js +167 -0
  23. package/tiledeskChatbotPlugs/CHANGELOG.md +2 -0
  24. package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +66 -46
  25. package/tiledeskChatbotPlugs/directives/DirClose.js +25 -0
  26. package/tiledeskChatbotPlugs/directives/DirDeflectToHelpCenter.js +6 -6
  27. package/tiledeskChatbotPlugs/directives/DirDepartment.js +52 -0
  28. package/tiledeskChatbotPlugs/directives/DirDisableInputText.js +45 -0
  29. package/tiledeskChatbotPlugs/directives/DirIntent.js +50 -0
  30. package/tiledeskChatbotPlugs/directives/DirMessage.js +5 -4
  31. package/tiledeskChatbotPlugs/directives/DirWhenOpen.js +95 -0
  32. package/tiledeskChatbotPlugs/directives/Directives.js +3 -0
  33. package/tiledeskChatbotPlugs/package.json +1 -1
  34. package/models/MongoDBIntentsDataSource.js +0 -22
  35. package/models/StaticIntentsDataSource.js +0 -110
  36. package/test/chatbot_query_test.js_ +0 -41
@@ -1,8 +1,8 @@
1
- let Faq = require('./faq');
2
- let Faq_kb = require('./faq_kb');
3
- const { ExtApi } = require('../ExtApi.js');
1
+ // let Faq = require('./faq');
2
+ // let Faq_kb = require('./faq_kb');
3
+ // const { ExtApi } = require('../ExtApi.js');
4
4
  const { MessagePipeline } = require('../tiledeskChatbotPlugs/MessagePipeline');
5
- const { DirectivesChatbotPlug } = require('../tiledeskChatbotPlugs/DirectivesChatbotPlug');
5
+ // const { DirectivesChatbotPlug } = require('../tiledeskChatbotPlugs/DirectivesChatbotPlug');
6
6
  const { WebhookChatbotPlug } = require('../tiledeskChatbotPlugs/WebhookChatbotPlug');
7
7
  const { TiledeskClient } = require('@tiledesk/tiledesk-client');
8
8
  const { IntentForm } = require('./IntentForm.js');
@@ -10,9 +10,23 @@ const { IntentForm } = require('./IntentForm.js');
10
10
  class TiledeskChatbot {
11
11
 
12
12
  constructor(config) {
13
+ if (!config.botsDataSource) {
14
+ throw new Error("config.botsDataSource is mandatory");
15
+ }
16
+ if (!config.intentsFinder) {
17
+ throw new Error("config.intentsFinder is mandatory");
18
+ }
19
+ if (!config.botId) {
20
+ throw new Error("config.botId is mandatory");
21
+ }
22
+ if (!config.bot) {
23
+ throw new Error("config.bot is mandatory");
24
+ }
25
+ this.botsDataSource = config.botsDataSource;
26
+ this.intentsFinder = config.intentsFinder;
13
27
  this.botId = config.botId;
28
+ this.bot = config.bot;
14
29
  this.token = config.token;
15
- this.faq_kb = config.faq_kb;
16
30
  this.tdcache = config.tdcache;
17
31
  this.APIURL = config.APIURL;
18
32
  this.APIKEY = config.APIKEY;
@@ -20,161 +34,197 @@ class TiledeskChatbot {
20
34
  this.projectId = config.projectId;
21
35
  this.log = config.log;
22
36
  }
23
-
37
+
24
38
  async replyToMessage(message, callback) {
25
39
  return new Promise( async (resolve, reject) => {
26
-
27
- const bot = await Faq_kb.findById(this.botId).select('+secret').exec();
28
- if (this.log) {console.log("bot:", bot);}
40
+ // get bot info
41
+ //let bot;
42
+ let lead = null;
43
+ if (message.request) {
44
+ this.request = message.request;
45
+ lead = message.request.lead;
46
+ }
29
47
 
48
+ // Checking locked intent
30
49
  const locked_intent = await this.currentLockedIntent(this.requestId);
31
50
  if (this.log) {console.log("got locked intent", locked_intent)}
32
51
  if (locked_intent) {
33
52
  const tdclient = new TiledeskClient({
34
- projectId: message.id_project,
53
+ projectId: this.projectId,
35
54
  token: this.token,
36
55
  APIURL: this.APIURL,
37
56
  APIKEY: this.APIKEY,
38
57
  log: false
39
58
  });
40
- const faqs = await tdclient.getIntents(this.botId, locked_intent, 0, 0, null);
41
- if (this.log) {console.log("locked intent. got faqs", faqs)}
42
- let reply = await this.execIntent(faqs, this.botId, message, bot);
59
+ // it only gets the locked_intent
60
+ const faq = await this.botsDataSource.getByIntentDisplayName(this.botId, locked_intent);
61
+ if (this.log) {console.log("locked intent. got faqs", faq)}
62
+ let reply;
63
+ if (faq) {
64
+ reply = await this.execIntent(faq, message, lead);//, bot);
65
+ }
66
+ else {
67
+ reply = {
68
+ "text": "An error occurred while getting locked intent:'" + locked_intent
69
+ }
70
+ }
43
71
  resolve(reply);
44
72
  return;
45
73
  }
46
- // CREATE TOKEN
47
- //var botWithSecret = await Faq_kb.findById(bot._id).select('+secret').exec();
48
- /*
49
- let signOptions = {
50
- issuer: 'https://tiledesk.com',
51
- subject: 'bot',
52
- audience: 'https://tiledesk.com/bots/'+bot._id,
53
- jwtid: uuidv4()
54
- };
55
-
56
- // DEPRECATED, REMOVE
57
- const bot_token = jwt.sign(bot.toObject(), bot.secret, signOptions);
58
- //console.log("bot_token:", bot_token);
59
- */
60
- // SETUP EXACT MATCH
61
- let query = { "id_project": this.projectId, "id_faq_kb": this.botId, "question": message.text };
62
- // BUT CHECKING ACTION BUTTON...
74
+
75
+ let explicit_intent_name = null;
76
+ // Explicit intent invocation
77
+ if (message.text.startsWith("/")) {
78
+ if (this.log) {console.log("Intent was explicitly invoked:", message.text);}
79
+ let intent_name = message.text.substring(message.text.indexOf("/") + 1);
80
+ if (this.log) {console.log("Invoked Intent:", intent_name);}
81
+ explicit_intent_name = intent_name;
82
+ // if (!message.attributes) {
83
+ // message.attributes = {}
84
+ // }
85
+ // message.attributes.action = intent_name;
86
+ // if (this.log) {console.log("Message action:", message.attributes.action)}
87
+ }
88
+
89
+ // Intent invocation with action
63
90
  if (message.attributes && message.attributes.action) {
64
- var action = message.attributes.action;
65
- var action_parameters_index = action.indexOf("?");
91
+ if (this.log) {console.log("Message has action:", message.attributes.action)}
92
+ explicit_intent_name = message.attributes.action;
93
+ /*let action_parameters_index = action.indexOf("?");
66
94
  if (action_parameters_index > -1) {
67
- action = action.substring(0, action_parameters_index);
95
+ intent_name = intent_name.substring(0, action_parameters_index);
96
+ }*/
97
+ if (this.log) {console.log("Intent was explicitly invoked with an action:", explicit_intent_name);}
98
+ }
99
+
100
+ // Checking Action button
101
+ if (explicit_intent_name) {
102
+ if (this.log) {console.log("Executing explicit intent:", explicit_intent_name)}
103
+ let faq = await this.botsDataSource.getByIntentDisplayName(this.botId, explicit_intent_name);
104
+ let reply;
105
+ if (faq) {
106
+ if (this.log) {console.log("Got a reply from Intent name:", faq);}
107
+ try {
108
+ reply = await this.execIntent(faq, message, lead);//, bot);
109
+ }
110
+ catch(error) {
111
+ console.error("error");
112
+ reject(error);
113
+ }
68
114
  }
69
- query = { "id_project": this.projectId, "id_faq_kb": this.botId, "intent_display_name": action };
115
+ else {
116
+ if (this.log) {console.log("No reply found by direct intent invocation:", explicit_intent_name);}
117
+ reply = {
118
+ "text": "No reply found by direct intent invocation: *" + explicit_intent_name + "*"
119
+ }
120
+ }
121
+ resolve(reply);
122
+ return;
70
123
  }
71
-
124
+
72
125
  // SEARCH INTENTS
73
- Faq.find(query).lean().exec(async (err, faqs) => {
74
- if (err) {
75
- return console.error("Error getting faq object.", err);
126
+ let faqs;
127
+ try {
128
+ faqs = await this.botsDataSource.getByExactMatch(this.botId, message.text);
129
+ }
130
+ catch (error) {
131
+ console.error("An error occurred during exact match:", error);
132
+ }
133
+ if (faqs && faqs.length > 0 && faqs[0].answer) {
134
+ if (this.log) {console.log("EXACT MATCH OR ACTION FAQ:", faqs[0]);}
135
+ let reply;
136
+ try {
137
+ reply = await this.execIntent(faqs[0], message, lead);//, bot);
76
138
  }
77
- if (faqs && faqs.length > 0 && faqs[0].answer) {
78
- if (this.log) {console.log("EXACT MATCH OR ACTION FAQ:", faqs[0]);}
79
- let reply = await this.execIntent(faqs, this.botId, message, bot);
80
- resolve(reply);
81
- //resolve(this.execIntent(faqs, this.botId, message, bot)); // bot_token
139
+ catch(error) {
140
+ console.error("error during exact match execIntent():", error);
141
+ reject(error);
142
+ return;
82
143
  }
83
- else { // FULL TEXT
84
- if (this.log) {console.log("NLP decode intent...");}
85
- query = { "id_project": this.projectId, "id_faq_kb": this.botId };
86
- var mongoproject = undefined;
87
- var sort = undefined;
88
- var search_obj = { "$search": message.text };
89
-
90
- if (this.faq_kb.language) {
91
- search_obj["$language"] = this.faq_kb.language;
92
- }
93
- query.$text = search_obj;
94
- //console.debug("fulltext search query", query);
95
-
96
- mongoproject = { score: { $meta: "textScore" } };
97
- sort = { score: { $meta: "textScore" } }
98
- // DA QUI RECUPERO LA RISPOSTA DATO (ID: SE EXT_AI) (QUERY FULLTEXT SE NATIVE-BASIC-AI)
99
- Faq.find(query, mongoproject).sort(sort).lean().exec(async (err, faqs) => {
100
- if (this.log) {console.log("Found:", faqs);}
101
- if (err) {
102
- console.error("Error:", err);
103
- }
104
- if (faqs && faqs.length > 0 && faqs[0].answer) {
105
- let reply = await this.execIntent(faqs, this.botId, message, bot);
106
- resolve(reply);
107
- }
108
- else {
109
- // fallback
110
- const fallbackIntent = await this.getIntentByDisplayName("defaultFallback", bot);
111
- const faqs = [fallbackIntent];
112
- let reply = await this.execIntent(faqs, this.botId, message, bot);
113
- resolve(reply); // bot_token
114
- }
115
- });
144
+ resolve(reply);
145
+ return;
146
+ }
147
+ else { // NLP
148
+ if (this.log) {console.log("NLP decode intent...");}
149
+ let intents;
150
+ try {
151
+ intents = await this.intentsFinder.decode(this.botId, message.text);
116
152
  }
117
- });
118
- });
119
- }
120
-
121
- getIntentByDisplayName(name, bot) {
122
- return new Promise((resolve, reject) => {
123
- var query = { "id_project": bot.id_project, "id_faq_kb": bot._id, "intent_display_name": name};
124
- if (this.log) {console.debug('query', query);}
125
- Faq.find(query).lean().exec( (err, faqs) => {
126
- if (err) {
127
- return reject(err);
153
+ catch(error) {
154
+ console.error("An error occurred:", error);
128
155
  }
129
- if (this.log) {console.debug("faqs", faqs);}
130
- if (faqs && faqs.length > 0) {
131
- const intent = faqs[0];
132
- return resolve(intent);
156
+ if (this.log) {console.log("NLP decoded found:", intents);}
157
+ if (intents && intents.length > 0) {
158
+ let faq = await this.botsDataSource.getByIntentDisplayName(this.botId, intents[0].intent_display_name);
159
+ let reply;
160
+ try {
161
+ reply = await this.execIntent(faq, message, lead);//, bot);
162
+ }
163
+ catch(error) {
164
+ console.error("error during NLP decoding:", error);
165
+ reject(error);
166
+ return;
167
+ }
168
+ resolve(reply);
169
+ return;
133
170
  }
134
171
  else {
135
- return resolve(null);
172
+ // fallback
173
+ let fallbackIntent = await this.botsDataSource.getByIntentDisplayName(this.botId, "defaultFallback");
174
+ if (!fallbackIntent) {
175
+ resolve(null);
176
+ return;
177
+ }
178
+ else {
179
+ let reply;
180
+ try {
181
+ reply = await this.execIntent(fallbackIntent, message, lead);//, bot);
182
+ }
183
+ catch(error) {
184
+ console.error("error during defaultFallback:", error);
185
+ reject(error);
186
+ return;
187
+ }
188
+ resolve(reply);
189
+ return;
190
+ }
136
191
  }
137
- });
192
+ }
138
193
  });
139
194
  }
140
-
141
- async execIntent(faqs, botId, message, bot) {
142
- answerObj = faqs[0];
143
- let sender = 'bot_' + botId;
144
- var answerObj;
145
- answerObj.score = 100; //exact search not set score
146
195
 
147
- const requestId = message.request.request_id;
148
- const projectId = message.id_project;
196
+ async execIntent(faq, message, lead) {//, bot) {
197
+ let answerObj = faq; // faqs[0];
198
+ const botId = this.botId;
199
+ let sender = 'bot_' + botId;
200
+ //var answerObj;
201
+ //answerObj.score = 100; // exact search has max score
149
202
  if (this.log) {
150
- console.log("requestId:", requestId)
203
+ console.log("requestId:", this.requestId)
151
204
  console.log("token:", this.token)
152
- console.log("projectId:", projectId)
205
+ console.log("projectId:", this.projectId)
153
206
  }
154
-
155
207
  if (this.tdcache) {
156
- const requestKey = "tilebot:" + requestId
208
+ const requestKey = "tilebot:" + this.requestId
157
209
  // best effort, do not "await", go on, trust redis speed.
158
- this.tdcache.setJSON(requestKey, message.request);
210
+ this.tdcache.setJSON(requestKey, this.request);
159
211
  }
160
212
  // /ext/:projectId/requests/:requestId/messages ENDPOINT COINCIDES
161
213
  // with API_ENDPOINT (APIRURL) ONLY WHEN THE TYBOT ROUTE IS HOSTED
162
214
  // ON THE MAIN SERVER. OTHERWISE WE USE TYBOT_ROUTE TO SPECIFY
163
215
  // THE ALTERNATIVE ROUTE.
164
- let extEndpoint = `${this.APIURL}/modules/tilebot/`;
165
- if (process.env.TYBOT_ENDPOINT) {
166
- extEndpoint = `${process.env.TYBOT_ENDPOINT}`;
167
- }
168
- const apiext = new ExtApi({
169
- ENDPOINT: extEndpoint,
170
- log: this.log
171
- });
172
- //console.log("the form...")
173
-
174
- // THE FORM
216
+ // let extEndpoint = `${this.APIURL}/modules/tilebot/`;
217
+ // if (process.env.TYBOT_ENDPOINT) {
218
+ // extEndpoint = `${process.env.TYBOT_ENDPOINT}`;
219
+ // }
220
+ // const apiext = new ExtApi({
221
+ // ENDPOINT: extEndpoint,
222
+ // log: this.log
223
+ // });
224
+ // console.log("the form...")
175
225
 
176
226
  let intent_name = answerObj.intent_display_name
177
- // THE FORM
227
+ // THE FORM
178
228
  if (intent_name === "test_form_intent") {
179
229
  answerObj.form = {
180
230
  "cancelCommands": ['annulla', 'cancella', 'reset', 'cancel'],
@@ -200,15 +250,16 @@ class TiledeskChatbot {
200
250
  };
201
251
  }
202
252
  let intent_form = answerObj.form;
203
- if (intent_form) {
204
- await this.lockIntent(requestId, intent_name);
253
+ if (this.log) {
254
+ console.log("IntentForm.isValidForm(intent_form)", IntentForm.isValidForm(intent_form));
255
+ }
256
+ if (IntentForm.isValidForm(intent_form)) {
257
+ await this.lockIntent(this.requestId, intent_name);
205
258
  const user_reply = message.text;
206
- //const intent_answer = answerObj.answer; //req.body.payload.text;
207
259
  let form_reply = await this.execIntentForm(user_reply, intent_form);
208
- //console.log("got form reply", form_reply)
209
- //if (form_reply_message) {
260
+ console.log("got form reply", form_reply)
210
261
  if (!form_reply.canceled && form_reply.message) {
211
- //console.log("Form replying for next field...");
262
+ console.log("Form replying for next field...");
212
263
  if (this.log) {console.log("Sending form reply...", form_reply.message)}
213
264
  // reply with this message (ex. please enter your fullname)
214
265
  if (!form_reply.message.attributes) {
@@ -218,24 +269,21 @@ class TiledeskChatbot {
218
269
  form_reply.message.attributes.splits = true;
219
270
  form_reply.message.attributes.markbot = true;
220
271
  return form_reply.message;
221
- //apiext.sendSupportMessageExt(form_reply.message, projectId, requestId, token, () => {
222
- // if (log) {console.log("FORM Message sent.", );}
223
- //});
224
- //return;
225
272
  }
226
273
  else if (form_reply.end) {
227
- //console.log("Form end.");
228
274
  if (this.log) {
229
- console.log("Form end.");
230
- console.log("Unlocking intent for request", requestId);
275
+ console.log("FORM end.", );
276
+ console.log("unlocking intent for request:", this.requestId);
277
+ }
278
+ this.unlockIntent(this.requestId);
279
+ if (lead) {
280
+ this.populatePrechatFormAndLead(this.requestId, lead._id);
231
281
  }
232
- this.unlockIntent(requestId);
233
- this.populatePrechatFormAndLead(message);
234
282
  }
235
283
  else if (form_reply.canceled) {
236
284
  console.log("Form canceled.");
237
- if (this.log) {console.log("unlocking intent due to canceling, for request", requestId);}
238
- this.unlockIntent(requestId);
285
+ if (this.log) {console.log("unlocking intent due to canceling, for request", this.requestId);}
286
+ this.unlockIntent(this.requestId);
239
287
  if (this.log) {console.log("sending form 'cancel' reply...", form_reply.message)}
240
288
  // reply with this message (ex. please enter your fullname)
241
289
  if (!form_reply.message.attributes) {
@@ -244,27 +292,20 @@ class TiledeskChatbot {
244
292
  form_reply.message.attributes.fillParams = true;
245
293
  form_reply.message.attributes.splits = true;
246
294
  return form_reply.message
247
- //apiext.sendSupportMessageExt(form_reply.message, projectId, requestId, token, () => {
248
- // if (log) {console.log("FORM Message sent.", );}
249
- //});
250
- //return;
251
295
  }
252
- //console.log("form_reply is", form_reply)
253
296
  }
254
-
255
297
  // FORM END
256
298
 
257
299
  const context = {
258
300
  payload: {
259
301
  botId: botId,
260
- bot: bot,
302
+ bot: this.bot,
261
303
  message: message, // USER MESSAGE (JSON)
262
304
  intent: answerObj
263
305
  },
264
306
  token: this.token
265
307
  };
266
-
267
- //console.log("the static_bot_answer...")
308
+
268
309
  const static_bot_answer = { // static design of the chatbot reply
269
310
  //type: answerObj.type,
270
311
  text: answerObj.answer,
@@ -276,10 +317,6 @@ class TiledeskChatbot {
276
317
  if (!static_bot_answer.attributes) {
277
318
  static_bot_answer.attributes = {}
278
319
  }
279
- /*let attr = static_bot_answer.attributes;
280
- if (!attr) {
281
- attr = {};
282
- }*/
283
320
  var timestamp = Date.now();
284
321
  static_bot_answer.attributes['clienttimestamp'] = timestamp;
285
322
  if (answerObj && answerObj._id) {
@@ -289,19 +326,15 @@ class TiledeskChatbot {
289
326
  // question_payload = clone of user's original message
290
327
  let question_payload = Object.assign({}, message);
291
328
  delete question_payload.request;
292
- let clonedfaqs = faqs.slice();
293
- if (clonedfaqs && clonedfaqs.length > 0) {
294
- clonedfaqs = clonedfaqs.shift()
295
- }
296
329
  const intent_info = {
297
- intent_name: answerObj.intent_display_name,
298
- is_fallback: false,
299
- confidence: answerObj.score,
300
- question_payload: question_payload,
301
- others: clonedfaqs
330
+ intent_name: answerObj.intent_display_name,
331
+ is_fallback: false,
332
+ confidence: answerObj.score,
333
+ question_payload: question_payload,
334
+ botId: this.botId,
335
+ bot: this.bot
302
336
  }
303
337
  static_bot_answer.attributes.intent_info = intent_info;
304
-
305
338
  static_bot_answer.attributes.directives = true;
306
339
  static_bot_answer.attributes.splits = true;
307
340
  static_bot_answer.attributes.markbot = true;
@@ -309,15 +342,8 @@ class TiledeskChatbot {
309
342
  static_bot_answer.attributes.webhook = answerObj.webhook_enabled;
310
343
 
311
344
  // exec webhook (only)
312
- const bot_answer = await this.execPipeline(static_bot_answer, message, bot, context, this.token);
313
-
314
- //bot_answer.text = await fillWithRequestParams(bot_answer.text, requestId); // move to "ext" pipeline
345
+ const bot_answer = await this.execPipeline(static_bot_answer, message, this.bot, context, this.token);
315
346
  return bot_answer;
316
-
317
- /*apiext.sendSupportMessageExt(bot_answer, projectId, requestId, token, () => {
318
- if (log) {console.log("Message sent");}
319
- });*/
320
-
321
347
  }
322
348
 
323
349
  async lockIntent(requestId, intent_name) {
@@ -325,7 +351,12 @@ class TiledeskChatbot {
325
351
  }
326
352
 
327
353
  async currentLockedIntent(requestId) {
328
- return await this.tdcache.get("tilebot:requests:" + requestId + ":locked");
354
+ if (this.tdcache) {
355
+ return await this.tdcache.get("tilebot:requests:" + requestId + ":locked");
356
+ }
357
+ else {
358
+ return null;
359
+ }
329
360
  }
330
361
 
331
362
  async unlockIntent(requestId) {
@@ -371,32 +402,27 @@ class TiledeskChatbot {
371
402
  return message;
372
403
  }
373
404
 
374
- async populatePrechatFormAndLead(message, callback) {
405
+ async populatePrechatFormAndLead(leadId, requestId) {
406
+ if (!leadId && !requestId) {
407
+ if (this.log) {console.log("(populatePrechatFormAndLead) !leadId && !requestId");}
408
+ return;
409
+ }
375
410
  const tdclient = new TiledeskClient({
376
411
  projectId: this.projectId,
377
412
  token: this.token,
378
413
  APIURL: this.APIURL,
379
414
  APIKEY: this.APIKEY
380
415
  });
381
-
382
- const leadId = message.request.lead._id;
383
- const requestId = message.request.request_id;
384
-
385
416
  const parameters_key = "tilebot:requests:" + requestId + ":parameters";
386
417
  const all_parameters = await this.tdcache.hgetall(parameters_key);
387
- if (all_parameters) {
388
- //console.log("all_parameters['userEmail']", all_parameters['userEmail'])
389
- //console.log("all_parameters['userFullname']", all_parameters['userFullname']);
418
+ if (all_parameters) {
390
419
  tdclient.updateLeadEmailFullname(leadId, null, all_parameters['userFullname'], () => {
391
- if (this.log) {console.log("lead updated.")}
420
+ if (this.log) {console.log("Lead updated.")}
392
421
  tdclient.updateRequestAttributes(requestId, {
393
422
  preChatForm: all_parameters,
394
423
  updated: Date.now
395
424
  }, () => {
396
- if (this.log) {console.log("prechat updated.");}
397
- if (callback) {
398
- callback();
399
- }
425
+ if (this.log) {console.log("Prechat updated.");}
400
426
  });
401
427
  });
402
428
  };
@@ -0,0 +1,90 @@
1
+
2
+ let axios = require('axios');
3
+
4
+ class TiledeskIntentsMachine {
5
+
6
+ constructor(config) {
7
+ if (!config.API_ENDPOINT) {
8
+ throw new Error("config.API_ENDPOINT is mandatory");
9
+ }
10
+ this.API_ENDPOINT = config.API_ENDPOINT;
11
+ this.log = config.log;
12
+ }
13
+
14
+ /**
15
+ * intentsFinder Adapter
16
+ * @param {String} text
17
+ * @returns the matching intents' names array
18
+ */
19
+ async decode(botId, text) {
20
+ return new Promise( (resolve, reject) => {
21
+ if (this.log) {console.log("NLP AI...");}
22
+ const url = `${this.API_ENDPOINT}/model/parse`;
23
+ if (this.log) {console.log("AI URL", url);}
24
+ const HTTPREQUEST = {
25
+ url: url,
26
+ headers: {
27
+ 'Content-Type' : 'application/json'
28
+ },
29
+ json: {
30
+ "text": text,
31
+ "botId": botId
32
+ },
33
+ method: 'POST'
34
+ };
35
+ this.myrequest(
36
+ HTTPREQUEST,
37
+ function(err, resbody) {
38
+ if (err) {
39
+ console.error("error:", err)
40
+ reject(err);
41
+ }
42
+ else {
43
+ resolve(resbody);
44
+ }
45
+ }, false
46
+ );
47
+ })
48
+ }
49
+
50
+ myrequest(options, callback, log) {
51
+ if (this.log) {
52
+ console.log("API URL:", options.url);
53
+ console.log("** Options:", options);
54
+ }
55
+ axios(
56
+ {
57
+ url: options.url,
58
+ method: options.method,
59
+ data: options.json,
60
+ params: options.params,
61
+ headers: options.headers
62
+ })
63
+ .then((res) => {
64
+ if (this.log) {
65
+ console.log("Response for url:", options.url);
66
+ console.log("Response headers:\n", res.headers);
67
+ //console.log("******** Response for url:", res);
68
+ }
69
+ if (res && res.status == 200 && res.data) {
70
+ if (callback) {
71
+ callback(null, res.data);
72
+ }
73
+ }
74
+ else {
75
+ if (callback) {
76
+ callback(TiledeskClient.getErr({message: "Response status not 200"}, options, res), null, null);
77
+ }
78
+ }
79
+ })
80
+ .catch( (error) => {
81
+ console.error("An error occurred:", error);
82
+ if (callback) {
83
+ callback(error, null, null);
84
+ }
85
+ });
86
+ }
87
+
88
+ }
89
+
90
+ module.exports = { TiledeskIntentsMachine }
@@ -0,0 +1,27 @@
1
+ var Faq_kb = require("./faq_kb");
2
+
3
+ class FaqKbService {
4
+
5
+ async getAll(options) {
6
+ if (!options) {
7
+ options = {
8
+ public: true,
9
+ certified: true
10
+ }
11
+ }
12
+ console.log("(Service) GET ALL FAQ_KBs");
13
+ return new Promise((resolve, reject) => {
14
+ let query = {public: options.public, certified: options.certified};
15
+ Faq_kb.find(query).lean().exec( (err, bots) => {
16
+ if (err) {
17
+ reject(err);
18
+ }
19
+ resolve(bots);
20
+ });
21
+ });
22
+ }
23
+
24
+ }
25
+
26
+ var faqKbService = new FaqKbService();
27
+ module.exports = faqKbService;
@@ -0,0 +1,22 @@
1
+ var Faq = require("./faq");
2
+ var Faq_kb = require("./faq_kb");
3
+
4
+ class FaqService {
5
+
6
+ async getAll(faq_kb_id) {
7
+ console.log("(Service) GET ALL FAQ OF THE BOT ID (req.query): ", faq_kb_id);
8
+ return new Promise((resolve, reject) => {
9
+ let query = { id_faq_kb: faq_kb_id};
10
+ Faq.find(query).lean().exec( (err, faqs) => {
11
+ if (err) {
12
+ reject(err);
13
+ }
14
+ resolve(faqs);
15
+ });
16
+ })
17
+ }
18
+
19
+ }
20
+
21
+ var faqService = new FaqService();
22
+ module.exports = faqService;