@tiledesk/tiledesk-tybot-connector 0.2.16 → 0.2.19

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,17 @@
5
5
  available on:
6
6
  ▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
7
7
 
8
+ ### v0.2.19
9
+ - Added native attribute lastUserMessageType
10
+ - Added integration with external intents decode engine
11
+ - Added support for automatic wait time on each reply
12
+
13
+ ### v0.2.17
14
+ - Added lastUserMessage JSON native attribute
15
+ - Added attributes to access image and file properties from incoming messages
16
+ - Added support for JSON attributes in conditions
17
+ - Added backupIntentsFinder based on Fulltext in TiledeskChatbot
18
+
8
19
  ### v0.2.16
9
20
  - update whatsapp api url for pre environment
10
21
 
@@ -230,9 +230,9 @@ class TiledeskExpression {
230
230
  }
231
231
 
232
232
  evaluateJavascriptExpression(expression, context) {
233
- // console.log("evaluating:", expression)
233
+ // console.log("(evaluateJavascriptExpression) evaluating:", expression)
234
234
  // console.log("context:", context)
235
- let res;
235
+ let res = null;
236
236
  try {
237
237
  const vm = new VM({
238
238
  timeout: 200,
@@ -240,9 +240,10 @@ class TiledeskExpression {
240
240
  sandbox: context
241
241
  });
242
242
  res = vm.run(`let $data = this;${expression}`);
243
+ // console.log("res=", res)
243
244
  }
244
245
  catch (err) {
245
- console.error("TiledeskExpression.evaluate() error:", err.message, "evaluating expression: '" + expression + "'");
246
+ console.error("(evaluateJavascriptExpression) TiledeskExpression.evaluate() error:", err.message, "evaluating expression: '" + expression + "'");
246
247
  }
247
248
  return res;
248
249
  }
@@ -324,11 +325,13 @@ class TiledeskExpression {
324
325
  // console.log("applyPattern:", applyPattern);
325
326
  let operand1_s;
326
327
  let is_valid_operand1 = TiledeskExpression.validateVariableName(condition.operand1);
328
+ // console.log("is_valid_operand1:", condition.operand1, is_valid_operand1);
327
329
  if (is_valid_operand1) {
328
330
  operand1_s = TiledeskExpression.variableOperand(condition.operand1);
331
+ // console.log("operand1_s:", operand1_s);
329
332
  }
330
333
  else {
331
- // console.error("Condition evaluation stopped because of invalid operand", condition.operand1);
334
+ console.error("Condition evaluation stopped because of invalid operand", condition.operand1);
332
335
  return null;
333
336
  }
334
337
 
@@ -343,24 +346,26 @@ class TiledeskExpression {
343
346
  operand2_s = TiledeskExpression.variableOperand(condition.operand2.name);
344
347
  }
345
348
  else {
346
- // console.error("Condition evaluation stopped because of invalid operand2", condition.operand2);
349
+ console.error("Condition evaluation stopped because of invalid operand2", condition.operand2);
347
350
  return null;
348
351
  }
349
352
  }
350
353
  else {
351
- // console.error("Condition evaluation stopped because of: No operand2", JSON.stringify(condition));
354
+ console.error("Condition evaluation stopped because of: No operand2", JSON.stringify(condition));
352
355
  return null;
353
356
  }
354
357
 
355
- // console.log("operand2_s:", operand2_s);
358
+ // console.log("operand1_s, operand2_s:",operand1_s, operand2_s);
356
359
  const expression =
357
360
  applyPattern
358
361
  .replace("#1", operand1_s)
359
362
  .replace("#2", operand2_s);
363
+ // console.log("expression is:", expression);
360
364
  return expression;
361
365
  }
362
366
 
363
367
  static JSONGroupToExpression(group, variables) {
368
+ // console.log("attributes:", variables);
364
369
  let conditions = group.conditions;
365
370
  let group_expression = "";
366
371
  // console.log("conditions:", conditions)
@@ -368,6 +373,7 @@ class TiledeskExpression {
368
373
  let part = conditions[i];
369
374
  if (part.type === "condition") {
370
375
  let expression = TiledeskExpression.JSONConditionToExpression(part, variables);
376
+ // console.log("returned expression:", expression);
371
377
  if (expression === null) {
372
378
  // console.error("Invalid JSON expression", JSON.stringify(part));
373
379
  return null;
@@ -412,7 +418,8 @@ class TiledeskExpression {
412
418
  static validateVariableName(variableName) {
413
419
  // console.log("variableName", variableName)
414
420
  // console.log("type of variableName:", typeof variableName);
415
- let matches = variableName.match(/^[a-zA-Z_]*[a-zA-Z_]+[a-zA-Z0-9_]*$/gm);
421
+ // let matches = variableName.match(/^[a-zA-Z_]*[a-zA-Z_]+[a-zA-Z0-9_]*$/gm);
422
+ let matches = variableName.match(/^[a-zA-Z_]+.*$/gm);
416
423
  // console.log("matches:", matches)
417
424
  if (matches !== null) {
418
425
  return true;
package/index.js CHANGED
@@ -102,8 +102,11 @@ router.post('/ext/:botid', async (req, res) => {
102
102
  if (log) {console.log("bot found:", JSON.stringify(bot));}
103
103
 
104
104
  let intentsMachine;
105
+ let backupMachine;
105
106
  if (!staticBots) {
106
107
  intentsMachine = IntentsMachineFactory.getMachine(bot, botId, projectId, log);
108
+ backupMachine = IntentsMachineFactory.getBackupMachine(bot, botId, projectId, log);
109
+ console.log("Created backupMachine:", backupMachine);
107
110
  }
108
111
  else {
109
112
  intentsMachine = {}
@@ -132,6 +135,7 @@ router.post('/ext/:botid', async (req, res) => {
132
135
  const chatbot = new TiledeskChatbot({
133
136
  botsDataSource: botsDS,
134
137
  intentsFinder: intentsMachine,
138
+ backupIntentsFinder: backupMachine,
135
139
  botId: botId,
136
140
  bot: bot,
137
141
  token: token,
@@ -257,7 +261,60 @@ async function updateRequestVariables(chatbot, message, projectId, requestId) {
257
261
  }
258
262
  if (message.text && message.sender !== "_tdinternal") {
259
263
  await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_TEXT_KEY, message.text);
264
+ await chatbot.addParameter("lastUserMessageType", message.type);
265
+ await chatbot.addParameter("lastUserMessage", lastUserMessageFrom(message)); // JSON TYPE *NEW
266
+ // get image
267
+ if (message.type && message.type === "image" && message.metadata) {
268
+ // "text": "\nimage text",
269
+ // "id_project": "65203e12f8c0cf002cf4110b",
270
+ // "createdBy": "8ac52a30-133f-4ee1-8b4b-96055bb81757",
271
+ // "metadata": {
272
+ // "height": 905,
273
+ // "name": "tiledesk_Open graph_general.png",
274
+ // "src": "https://firebasestorage.googleapis.com/v0/b/chat21-pre-01.appspot.com/o/public%2Fimages%2F8ac52a30-133f-4ee1-8b4b-96055bb81757%2Fda5bbc8d-5174-49a8-a041-3d9355242da5%2Ftiledesk_Open%20graph_general.png?alt=media&token=be82fecb-3cd1-45b9-a135-c2c57a932862",
275
+ // "type": "image/png",
276
+ // "uid": "lo68iyq5",
277
+ // "width": 1724
278
+ // }
279
+ if (message.metadata.src) {
280
+ await chatbot.addParameter("lastUserImageURL", message.metadata.src);
281
+ await chatbot.addParameter("lastUserImageName", message.metadata.name);
282
+ await chatbot.addParameter("lastUserImageWidth", message.metadata.width);
283
+ await chatbot.addParameter("lastUserImageHeight", message.metadata.height);
284
+ await chatbot.addParameter("lastUserImageType", message.metadata.type);
285
+ }
286
+ }
287
+ else {
288
+ await chatbot.addParameter("lastUserImageURL", null);
289
+ await chatbot.addParameter("lastUserImageName", null);
290
+ await chatbot.addParameter("lastUserImageWidth", null);
291
+ await chatbot.addParameter("lastUserImageHeight", null);
292
+ await chatbot.addParameter("lastUserImageType", null);
293
+ }
294
+ // get document
295
+ if (message.type && message.type === "file" && message.metadata) {
296
+ // "type": "file",
297
+ // "text": "[LIBRETTO-WEB-ISTRUZIONI-GENITORI.pdf](https://firebasestorage.googleapis.com/v0/b/chat21-pre-01.appspot.com/o/public%2Fimages%2F8ac52a30-133f-4ee1-8b4b-96055bb81757%2F502265ee-4f4a-47a4-9375-172bb0e6bf39%2FLIBRETTO-WEB-ISTRUZIONI-GENITORI.pdf?alt=media&token=a09d065a-9b56-4507-8960-344cc294e4d1)\nistruzioni",
298
+ // "metadata": {
299
+ // "name": "LIBRETTO-WEB-ISTRUZIONI-GENITORI.pdf",
300
+ // "src": "https://firebasestorage.googleapis.com/v0/b/chat21-pre-01.appspot.com/o/public%2Fimages%2F8ac52a30-133f-4ee1-8b4b-96055bb81757%2F502265ee-4f4a-47a4-9375-172bb0e6bf39%2FLIBRETTO-WEB-ISTRUZIONI-GENITORI.pdf?alt=media&token=a09d065a-9b56-4507-8960-344cc294e4d1",
301
+ // "type": "application/pdf",
302
+ // "uid": "lo68oz8i"
303
+ // }
304
+ if (message.metadata.src) {
305
+ await chatbot.addParameter("lastUserDocumentURL", message.metadata.src);
306
+ await chatbot.addParameter("lastUserDocumentName", message.metadata.name);
307
+ await chatbot.addParameter("lastUserDocumentType", message.metadata.type);
308
+ }
309
+ }
310
+ else {
311
+ await chatbot.addParameter("lastUserDocumentURL", null);
312
+ await chatbot.addParameter("lastUserDocumentName", null);
313
+ await chatbot.addParameter("lastUserDocumentType", null);
314
+ }
260
315
  }
316
+
317
+
261
318
  await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_MESSAGE_ID_KEY, messageId);
262
319
  if (message.request && message.request.location && message.request.location.country) {
263
320
  await chatbot.addParameter(TiledeskChatbotConst.REQ_COUNTRY_KEY, message.request.location.country);
@@ -325,7 +382,7 @@ async function updateRequestVariables(chatbot, message, projectId, requestId) {
325
382
  }
326
383
  }
327
384
  if (chatbot.log) {
328
- console.log("tdcache:", chatbot.tdcache);
385
+ // console.log("tdcache:", chatbot.tdcache);
329
386
  console.log("requestId:", requestId);
330
387
  console.log("KEY:", TiledeskChatbotConst.REQ_PROJECT_ID_KEY);
331
388
  let proj_ = await TiledeskChatbot.getParameterStatic(chatbot.tdcache, requestId, TiledeskChatbotConst.REQ_PROJECT_ID_KEY);
@@ -366,6 +423,23 @@ async function updateRequestVariables(chatbot, message, projectId, requestId) {
366
423
  // }
367
424
  }
368
425
 
426
+ function lastUserMessageFrom(msg) {
427
+ let message = {};
428
+ message["senderFullname"] = msg["senderFullname"]; // ex. "Bot"
429
+ message["type"] = msg["type"]; // ex. "text",
430
+ message["channel_type"] = msg["channel_type"]; // ex. "group",
431
+ message["status"] = msg["status"]; // ex. 0,
432
+ message["id"] = msg["_id"]; // ex. "6538cda46cb4d8002cf2317a",
433
+ message["sender"] = msg["sender"]; // ex. "system",
434
+ message["recipient"] = msg["recipient"]; // ex. "support-group-65203e12f8c0cf002cf4110b-4066a69c8b464646a3ff25f9f41575bb",
435
+ message["text"] = msg["text"]; // ex. "\\start",
436
+ message["createdBy"] = msg["createdBy"]; // ex. "system",
437
+ message["attributes"] = msg["attributes"]; // ex. { "subtype": "info" }
438
+ message["metadata"] = msg["metadata"];
439
+ message["channel"] = msg["channel"]; // ex. { "name": "chat21" }
440
+ return message;
441
+ }
442
+
369
443
  function actionsToDirectives(actions) {
370
444
  let directives = [];
371
445
  if (actions && actions.length > 0) {
@@ -13,12 +13,18 @@ class IntentsMachineFactory {
13
13
  });
14
14
  }
15
15
  else {
16
- console.log("bot.intentsEngine is null");
17
16
  if (log) {console.log("Setting MongodbIntentsMachine with bot:", JSON.stringify(bot));}
18
17
  machine = new MongodbIntentsMachine({projectId: projectId, language: bot.language, log});
19
18
  }
20
19
  return machine;
21
20
  }
21
+
22
+ static getBackupMachine(bot, botId, projectId, log) {
23
+ let machine;
24
+ if (log) {console.log("Setting MongodbIntentsMachine as Backup Intents Machine on bot:", JSON.stringify(bot));}
25
+ machine = new MongodbIntentsMachine({projectId: projectId, language: bot.language, log});
26
+ return machine;
27
+ }
22
28
  }
23
29
 
24
30
  module.exports = { IntentsMachineFactory }
@@ -29,6 +29,7 @@ class TiledeskChatbot {
29
29
  }
30
30
  this.botsDataSource = config.botsDataSource;
31
31
  this.intentsFinder = config.intentsFinder;
32
+ this.backupIntentsFinder = config.backupIntentsFinder;
32
33
  this.botId = config.botId;
33
34
  this.bot = config.bot;
34
35
  this.token = config.token;
@@ -79,7 +80,7 @@ class TiledeskChatbot {
79
80
  if (this.log) {console.log("RESETTING LOCKED INTENT. Intent was explicitly invoked with an action:", message.attributes.action);}
80
81
  await this.unlockIntent(this.requestId);
81
82
  await this.unlockAction(this.requestId);
82
- if (this.log) {console.log("RESET LOCKED INTENT. Intent was explicitly invoked with an action:", message.attributes.action);}
83
+ if (this.log) {console.log("RESET LOCKED INTENT. Intent was explicitly invoked with an action:", message.attributes.action);}
83
84
  }
84
85
  }
85
86
  catch(error) {
@@ -151,7 +152,7 @@ class TiledeskChatbot {
151
152
 
152
153
  let explicit_intent_name = null;
153
154
  // Explicit intent invocation
154
- if (message.text.startsWith("/")) {
155
+ if (message.text && message.text.startsWith("/")) {
155
156
  if (this.log) {console.log("Intent was explicitly invoked:", message.text);}
156
157
  let intent_name = message.text.substring(message.text.indexOf("/") + 1);
157
158
  if (this.log) {console.log("Invoked Intent:", intent_name);}
@@ -274,16 +275,24 @@ class TiledeskChatbot {
274
275
  return;
275
276
  }
276
277
  else { // NLP
277
- if (this.log) {console.log("Chatbot NLP decode intent...");}
278
+ if (this.log) {console.log("Chatbot NLP decoding intent...");}
278
279
  let intents;
279
280
  try {
280
281
  intents = await this.intentsFinder.decode(this.botId, message.text);
282
+ if (this.log) {console.log("Tiledesk AI intents found:", intents);}
281
283
  }
282
284
  catch(error) {
283
- console.error("An error occurred:", error);
285
+ console.error("An error occurred on IntentsFinder.decode() (/model/parse error):", error.message);
286
+ // recover on fulltext
287
+ if (this.backupIntentsFinder) {
288
+ if (this.log) {console.log("using backup Finder:", this.backupIntentsFinder);}
289
+ intents = await this.backupIntentsFinder.decode(this.botId, message.text);
290
+ if (this.log) {console.log("Got intents from backup finder:", intents);}
291
+ }
284
292
  }
285
- if (this.log) {console.log("NLP decoded found:", intents);}
293
+ if (this.log) {console.log("NLP intents found:", intents);}
286
294
  if (intents && intents.length > 0) {
295
+ console.log("Matching intents found.");
287
296
  // let faq = await this.botsDataSource.getByIntentDisplayName(this.botId, intents[0].intent_display_name);
288
297
  let faq = await this.botsDataSource.getByIntentDisplayNameCache(this.botId, intents[0].intent_display_name, this.tdcache);
289
298
  let reply;
@@ -233,6 +233,25 @@ class TiledeskChatbotUtil {
233
233
  }
234
234
  }
235
235
 
236
+ static totalMessageWait(message) {
237
+ if (!message) {
238
+ return;
239
+ }
240
+ console.log("compute delay...", message)
241
+ if (message.attributes.commands.length > 0) {
242
+ console.log("going on delay")
243
+ let commands = message.attributes.commands;
244
+ console.log("got commands", commands)
245
+ let totalWaitTime = 0;
246
+ for (let i = commands.length - 1; i >= 0; i--) {
247
+ if (commands[i].type === "wait") { // is a wait
248
+ totalWaitTime += commands[i].time;
249
+ }
250
+ }
251
+ return totalWaitTime;
252
+ }
253
+ }
254
+
236
255
  static fillCommandAttachments(command, variables, log) {
237
256
  if (log) {
238
257
  console.log("filling command button:", JSON.stringify(command))
@@ -37,13 +37,14 @@ class TiledeskIntentsMachine {
37
37
  };
38
38
  this.myrequest(
39
39
  HTTPREQUEST,
40
- function(err, resbody) {
40
+ (err, resbody) => {
41
41
  if (err) {
42
- console.error("error:", err)
42
+ // console.error("An error occurred on /model/parse:", err)
43
43
  reject(err);
44
44
  }
45
45
  else {
46
- resolve(resbody);
46
+ console.log("Tiledesk AI replied:", resbody)
47
+ resolve(this.translateForTiledesk(resbody));
47
48
  }
48
49
  }, false
49
50
  );
@@ -83,7 +84,7 @@ class TiledeskIntentsMachine {
83
84
  // }
84
85
  let intents_array = intents.intent_ranking;
85
86
  let tiledesk_intents = [];
86
- for (i = 0; i < intents_array.length; i++) {
87
+ for (let i = 0; i < intents_array.length; i++) {
87
88
  let td_intent = {
88
89
  "intent_display_name": intents_array[i].name
89
90
  }
@@ -123,7 +124,7 @@ class TiledeskIntentsMachine {
123
124
  }
124
125
  })
125
126
  .catch( (error) => {
126
- console.error("An error occurred:", error);
127
+ // console.error("An error occurred:", error);
127
128
  if (callback) {
128
129
  callback(error, null, null);
129
130
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-tybot-connector",
3
- "version": "0.2.16",
3
+ "version": "0.2.19",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -80,6 +80,7 @@ class DirIntent {
80
80
  else {
81
81
  console.error("Invalid intent");
82
82
  callback();
83
+ return;
83
84
  }
84
85
 
85
86
  // if (intentName) {
@@ -106,7 +106,18 @@ class DirReply {
106
106
  console.error("Error sending reply:", err);
107
107
  }
108
108
  if (this.log) {console.log("Reply message sent");}
109
- callback();
109
+ const delay = TiledeskChatbotUtil.totalMessageWait(message);
110
+ console.log("got total delay:", delay)
111
+ if (delay > 0 && delay <= 30000) { // prevent long delays
112
+ setTimeout(() => {
113
+ console.log("callback after delay")
114
+ callback();
115
+ }, delay);
116
+ }
117
+ else {
118
+ console.log("invalid delay.")
119
+ callback();
120
+ }
110
121
  });
111
122
 
112
123
  // this.sendSupportMessage(