@tiledesk/tiledesk-tybot-connector 2.0.38 → 2.0.40

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 (48) hide show
  1. package/engine/TiledeskChatbot.js +60 -3
  2. package/engine/mock/MockBotsDataSource.js +1 -1
  3. package/index.js +154 -3
  4. package/logs/app.log +110 -0
  5. package/package.json +1 -1
  6. package/services/TilebotService.js +36 -0
  7. package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +100 -519
  8. package/tiledeskChatbotPlugs/directives/DirAddKbContent.js +1 -1
  9. package/tiledeskChatbotPlugs/directives/DirAddTags.js +1 -1
  10. package/tiledeskChatbotPlugs/directives/DirAiCondition.js +1 -1
  11. package/tiledeskChatbotPlugs/directives/DirAiPrompt.js +1 -1
  12. package/tiledeskChatbotPlugs/directives/DirAskGPTV2.js +2 -2
  13. package/tiledeskChatbotPlugs/directives/DirAssistant.js +1 -1
  14. package/tiledeskChatbotPlugs/directives/DirBrevo.js +1 -1
  15. package/tiledeskChatbotPlugs/directives/DirCaptureUserReply.js +1 -1
  16. package/tiledeskChatbotPlugs/directives/DirClearTranscript.js +1 -1
  17. package/tiledeskChatbotPlugs/directives/DirClose.js +1 -1
  18. package/tiledeskChatbotPlugs/directives/DirCode.js +1 -1
  19. package/tiledeskChatbotPlugs/directives/DirCondition.js +1 -1
  20. package/tiledeskChatbotPlugs/directives/DirContactUpdate.js +1 -1
  21. package/tiledeskChatbotPlugs/directives/DirCustomerio.js +1 -1
  22. package/tiledeskChatbotPlugs/directives/DirDeleteVariable.js +1 -1
  23. package/tiledeskChatbotPlugs/directives/DirDepartment.js +1 -1
  24. package/tiledeskChatbotPlugs/directives/DirFlowLog.js +1 -1
  25. package/tiledeskChatbotPlugs/directives/DirGptTask.js +1 -1
  26. package/tiledeskChatbotPlugs/directives/DirHubspot.js +1 -1
  27. package/tiledeskChatbotPlugs/directives/DirIfOnlineAgentsV2.js +1 -1
  28. package/tiledeskChatbotPlugs/directives/DirIfOpenHours.js +1 -1
  29. package/tiledeskChatbotPlugs/directives/DirIntent.js +4 -0
  30. package/tiledeskChatbotPlugs/directives/DirJSONCondition.js +1 -1
  31. package/tiledeskChatbotPlugs/directives/DirMake.js +1 -1
  32. package/tiledeskChatbotPlugs/directives/DirMoveToAgent.js +1 -1
  33. package/tiledeskChatbotPlugs/directives/DirMoveToUnassigned.js +1 -1
  34. package/tiledeskChatbotPlugs/directives/DirQapla.js +1 -1
  35. package/tiledeskChatbotPlugs/directives/DirRandomReply.js +1 -1
  36. package/tiledeskChatbotPlugs/directives/DirReplaceBot.js +1 -1
  37. package/tiledeskChatbotPlugs/directives/DirReplaceBotV2.js +1 -1
  38. package/tiledeskChatbotPlugs/directives/DirReplaceBotV3.js +1 -1
  39. package/tiledeskChatbotPlugs/directives/DirReply.js +10 -2
  40. package/tiledeskChatbotPlugs/directives/DirReplyV2.js +1 -1
  41. package/tiledeskChatbotPlugs/directives/DirSendEmail.js +1 -1
  42. package/tiledeskChatbotPlugs/directives/DirSendWhatsapp.js +1 -1
  43. package/tiledeskChatbotPlugs/directives/DirSetAttributeV2.js +1 -1
  44. package/tiledeskChatbotPlugs/directives/DirWait.js +1 -1
  45. package/tiledeskChatbotPlugs/directives/DirWebRequestV2.js +1 -1
  46. package/tiledeskChatbotPlugs/directives/DirWebResponse.js +1 -1
  47. package/tiledeskChatbotPlugs/directives/DirWhatsappByAttribute.js +1 -1
  48. package/utils/TiledeskChatbotUtil.js +131 -141
@@ -18,9 +18,9 @@ class TiledeskChatbot {
18
18
  if (!config.botsDataSource) {
19
19
  throw new Error("config.botsDataSource is mandatory");
20
20
  }
21
- if (!config.intentsFinder) {
22
- throw new Error("config.intentsFinder is mandatory");
23
- }
21
+ // if (!config.intentsFinder) {
22
+ // throw new Error("config.intentsFinder is mandatory");
23
+ // }
24
24
  if (!config.botId) {
25
25
  throw new Error("config.botId is mandatory");
26
26
  }
@@ -253,6 +253,63 @@ class TiledeskChatbot {
253
253
  }
254
254
  });
255
255
  }
256
+
257
+ async findBlock(message, callback) {
258
+ return new Promise( async (resolve, reject) => {
259
+ let lead = null;
260
+ if (message.request) {
261
+ this.request = message.request;
262
+ }
263
+
264
+ let explicit_intent_name = null;
265
+ // Explicit intent invocation
266
+ if (message.text && message.text.startsWith("/")) {
267
+ winston.verbose("(TiledeskChatbot) Intent was explicitly invoked: " + message.text);
268
+ let intent_name = message.text.substring(message.text.indexOf("/") + 1);
269
+ winston.verbose("(TiledeskChatbot) Invoked Intent: " + intent_name)
270
+ explicit_intent_name = intent_name;
271
+ }
272
+
273
+ // Intent invocation with action
274
+ if (message.attributes && message.attributes.action) {
275
+ winston.debug("(TiledeskChatbot) Message has action: ", message.attributes.action)
276
+ explicit_intent_name = message.attributes.action;
277
+ winston.verbose("(TiledeskChatbot) Intent was explicitly invoked with an action:", explicit_intent_name)
278
+ }
279
+
280
+ if (explicit_intent_name) {
281
+ winston.verbose("(TiledeskChatbot) Processing explicit intent:", explicit_intent_name)
282
+ // look for parameters
283
+ const intent = TiledeskChatbotUtil.parseIntent(explicit_intent_name);
284
+ winston.debug("(TiledeskChatbot) parsed intent:", intent);
285
+ let reply;
286
+ if (!intent || (intent && !intent.name)) {
287
+ winston.verbose("(TiledeskChatbot) Invalid intent:", explicit_intent_name)
288
+ reply = { "text": "Invalid intent: *" + explicit_intent_name + "*" }
289
+ resolve();
290
+ }
291
+ else {
292
+ winston.verbose("(TiledeskChatbot) Processing intent:", explicit_intent_name)
293
+ let faq = await this.botsDataSource.getByIntentDisplayNameCache(this.botId, intent.name, this.tdcache);
294
+ // console.log("faq: ", JSON.stringify(faq, null, 2))
295
+
296
+ if (faq) {
297
+ if (faq.actions) {
298
+ // Qui viene aggiornata faq perchè l'oggetto in js viene passato per riferimento. Viene modificato l'oggetto originale anche senza un return.
299
+ TiledeskChatbotUtil.addConnectAction(faq);
300
+ }
301
+ resolve(faq)
302
+ return;
303
+ }
304
+ else {
305
+ winston.verbose("(TiledeskChatbot) Intent not found: " + explicit_intent_name);
306
+ reply = { "text": "Intent not found: " + explicit_intent_name }
307
+ resolve()
308
+ }
309
+ }
310
+ }
311
+ });
312
+ }
256
313
 
257
314
  async execIntent(faq, message, lead) {//, bot) {
258
315
  let answerObj = faq; // faqs[0];
@@ -38,7 +38,7 @@ class MockBotsDataSource {
38
38
  * @returns an Array of matches
39
39
  */
40
40
  async getByExactMatch(botId, text) {
41
- const intent_display_name = this.data.bots[botId].questions_intent[text];
41
+ const intent_display_name = this.data.bots[botId].questions_intent?.[text];
42
42
  if (intent_display_name) {
43
43
  return [this.data.bots[botId].intents[intent_display_name]];
44
44
  }
package/index.js CHANGED
@@ -44,6 +44,7 @@ let staticBots;
44
44
  router.post('/ext/:botid', async (req, res) => {
45
45
  const botId = req.params.botid;
46
46
  winston.verbose("(tybotRoute) POST /ext/:botid called: " + botId)
47
+
47
48
  if(!botId || botId === "null" || botId === "undefined"){
48
49
  return res.status(400).send({"success": false, error: "Required parameters botid not found. Value is 'null' or 'undefined'"})
49
50
  }
@@ -133,9 +134,14 @@ router.post('/ext/:botid', async (req, res) => {
133
134
  });
134
135
  winston.verbose("(tybotRoute) Message text: " + message.text)
135
136
 
136
- await TiledeskChatbotUtil.updateRequestAttributes(chatbot, token, message, projectId, requestId);
137
- if (requestId.startsWith("support-group-")) {
138
- await TiledeskChatbotUtil.updateConversationTranscript(chatbot, message);
137
+ try {
138
+ await TiledeskChatbotUtil.updateRequestAttributes(chatbot, token, message, projectId, requestId);
139
+ if (requestId.startsWith("support-group-")) {
140
+ await TiledeskChatbotUtil.updateConversationTranscript(chatbot, message);
141
+ }
142
+ } catch (e) {
143
+ winston.error("Error on /ext updating request attributes or transcript: ", e)
144
+ return;
139
145
  }
140
146
 
141
147
  let reply = null;
@@ -199,6 +205,151 @@ router.post('/ext/:botid', async (req, res) => {
199
205
 
200
206
  });
201
207
 
208
+ router.post('/exec/:botid', async (req, res) => {
209
+
210
+ const botId = req.params.botid;
211
+ winston.verbose("(tybotRoute) POST /exec/:botid called: " + botId);
212
+ if(!botId || botId === "null" || botId === "undefined"){
213
+ return res.status(400).send({"success": false, error: "Required parameters botid not found. Value is 'null' or 'undefined'"})
214
+ }
215
+
216
+ if (req && req.body && req.body.payload && req.body.payload.request && req.body.payload.request.snapshot) {
217
+ delete req.body.payload.request.snapshot;
218
+ }
219
+ winston.verbose("(tybotRoute) Request Body: ", req.body);
220
+
221
+ const message = req.body.payload;
222
+ const messageId = message._id;
223
+ const token = req.body.token;
224
+ const requestId = message.request.request_id;
225
+ const projectId = message.id_project;
226
+ winston.verbose("(tybotRoute) message.id_project: " + message.id_project)
227
+
228
+ // adding info for internal context workflow
229
+ message.request.bot_id = botId;
230
+ if (message.request.id_project === null || message.request.id_project === undefined) {
231
+ message.request.id_project = projectId;
232
+ }
233
+
234
+ //skip internal note messages
235
+ if(message && message.attributes && message.attributes.subtype === 'private') {
236
+ winston.verbose("(tybotRoute) Skipping internal note message: " + message.text);
237
+ return res.status(200).send({"success":true});
238
+ }
239
+
240
+ // validate reuqestId
241
+ let isValid = TiledeskChatbotUtil.validateRequestId(requestId, projectId);
242
+ if (isValid) {
243
+ res.status(200).send({"success":true});
244
+ }
245
+ else {
246
+ res.status(400).send({"success": false, error: "Request id is invalid:" + requestId + " for projectId:" + projectId + "chatbotId:" + botId});
247
+ return;
248
+ }
249
+
250
+ const request_botId_key = "tilebot:botId_requests:" + requestId;
251
+ await tdcache.set(
252
+ request_botId_key,
253
+ botId,
254
+ {EX: 604800} // 7 days
255
+ );
256
+
257
+ let botsDS;
258
+ if (!staticBots) {
259
+ botsDS = new MongodbBotsDataSource({projectId: projectId, botId: botId});
260
+ winston.verbose("(tybotRoute) botsDS created with Mongo");
261
+ }
262
+ else {
263
+ botsDS = new MockBotsDataSource(staticBots);
264
+ }
265
+
266
+ // get the bot metadata
267
+ let bot = await botsDS.getBotByIdCache(botId, tdcache).catch((err)=> {
268
+ Promise.reject(err);
269
+ return;
270
+ });
271
+
272
+ let intentsMachine;
273
+ let backupMachine;
274
+
275
+ const chatbot = new TiledeskChatbot({
276
+ botsDataSource: botsDS,
277
+ intentsFinder: intentsMachine,
278
+ backupIntentsFinder: backupMachine,
279
+ botId: botId,
280
+ bot: bot,
281
+ token: token,
282
+ APIURL: API_ENDPOINT,
283
+ APIKEY: "___",
284
+ tdcache: tdcache,
285
+ requestId: requestId,
286
+ projectId: projectId,
287
+ MAX_STEPS: MAX_STEPS,
288
+ MAX_EXECUTION_TIME: MAX_EXECUTION_TIME
289
+ });
290
+ winston.verbose("(tybotRoute) Message text: " + message.text);
291
+
292
+ let reply = null;
293
+ try {
294
+ reply = await chatbot.findBlock(message);
295
+ }
296
+ catch (err) {
297
+ winston.error("(tybotRoute) An error occurred replying to message: ", err);
298
+ return;
299
+ }
300
+ if (!reply) {
301
+ winston.verbose("(tybotRoute) No reply. Stop flow.")
302
+ return;
303
+ }
304
+
305
+ if (reply.actions && reply.actions.length > 0) { // structured actions (coming from chatbot designer)
306
+ try {
307
+ winston.debug("(tybotRoute) Reply actions: ", reply.actions)
308
+ let directives = TiledeskChatbotUtil.actionsToDirectives(reply.actions);
309
+ winston.debug("(tybotRoute) the directives:", directives)
310
+ let directivesPlug = new DirectivesChatbotPlug(
311
+ {
312
+ message: message,
313
+ reply: reply,
314
+ directives: directives,
315
+ chatbot: chatbot,
316
+ supportRequest: message.request,
317
+ API_ENDPOINT: API_ENDPOINT,
318
+ TILEBOT_ENDPOINT:TILEBOT_ENDPOINT,
319
+ token: token,
320
+ // HELP_CENTER_API_ENDPOINT: process.env.HELP_CENTER_API_ENDPOINT,
321
+ cache: tdcache
322
+ }
323
+ );
324
+ directivesPlug.processDirectives( () => {
325
+ winston.verbose("(tybotRoute) Actions - Directives executed.");
326
+ });
327
+ }
328
+ catch (error) {
329
+ winston.error("(tybotRoute) Error while processing actions:", error);
330
+ }
331
+ }
332
+ else { // text answer (parse text directives to get actions)
333
+ winston.verbose("(tybotRoute) No actions. Reply text: ", reply.text)
334
+ reply.triggeredByMessageId = messageId;
335
+ if (!reply.attributes) {
336
+ reply.attributes = {}
337
+ }
338
+ reply.attributes.directives = true;
339
+ reply.attributes.splits = true;
340
+ reply.attributes.markbot = true;
341
+ reply.attributes.fillParams = true;
342
+
343
+ const apiext = new ExtApi({
344
+ TILEBOT_ENDPOINT: TILEBOT_ENDPOINT
345
+ });
346
+ apiext.sendSupportMessageExt(reply, projectId, requestId, token, () => {
347
+ winston.verbose("(tybotRoute) sendSupportMessageExt reply sent: ", reply)
348
+ });
349
+ }
350
+
351
+ })
352
+
202
353
  router.post('/ext/:projectId/requests/:requestId/messages', async (req, res) => {
203
354
  res.json({success:true});
204
355
  const projectId = req.params.projectId;