@tiledesk/tiledesk-tybot-connector 0.2.601-rc1 → 0.3.1

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 (73) hide show
  1. package/CHANGELOG.md +387 -1
  2. package/ExtApi.js +6 -7
  3. package/Logger.js +74 -0
  4. package/TdCache.js +81 -176
  5. package/TdCache_v3.js +261 -0
  6. package/TiledeskExpression.js +7 -3
  7. package/TiledeskServices/AIService.js +43 -0
  8. package/TiledeskServices/utils.js +99 -0
  9. package/index.js +305 -50
  10. package/logs/app.log +279 -0
  11. package/models/IntentsMachineFactory.js +5 -2
  12. package/models/MockBotsDataSource.js +19 -11
  13. package/models/TiledeskChatbot.js +97 -79
  14. package/models/TiledeskChatbotConst.js +12 -17
  15. package/models/TiledeskChatbotUtil.js +359 -109
  16. package/models/TiledeskIntentsMachine.js +1 -1
  17. package/models/faqKbService.js +1 -1
  18. package/package.json +8 -6
  19. package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +172 -106
  20. package/tiledeskChatbotPlugs/Filler.js +13 -2
  21. package/tiledeskChatbotPlugs/TildeskContextForCodeOrchestrator.js +8 -0
  22. package/tiledeskChatbotPlugs/WebhookChatbotPlug.js +13 -7
  23. package/tiledeskChatbotPlugs/directives/DirAddTags.js +374 -0
  24. package/tiledeskChatbotPlugs/directives/DirAiPrompt.js +476 -0
  25. package/tiledeskChatbotPlugs/directives/DirAskGPT.js +16 -19
  26. package/tiledeskChatbotPlugs/directives/DirAskGPTV2.js +221 -34
  27. package/tiledeskChatbotPlugs/directives/DirAssign.js +0 -11
  28. package/tiledeskChatbotPlugs/directives/DirAssignFromFunction.js +11 -21
  29. package/tiledeskChatbotPlugs/directives/DirAssistant.js +728 -0
  30. package/tiledeskChatbotPlugs/directives/DirBrevo.js +353 -0
  31. package/tiledeskChatbotPlugs/directives/DirCaptureUserReply.js +3 -30
  32. package/tiledeskChatbotPlugs/directives/DirClearTranscript.js +22 -0
  33. package/tiledeskChatbotPlugs/directives/DirClose.js +16 -3
  34. package/tiledeskChatbotPlugs/directives/DirCode.js +1 -1
  35. package/tiledeskChatbotPlugs/directives/DirCondition.js +0 -26
  36. package/tiledeskChatbotPlugs/directives/DirConnectBlock.js +182 -0
  37. package/tiledeskChatbotPlugs/directives/DirContactUpdate.js +121 -0
  38. package/tiledeskChatbotPlugs/directives/DirCustomerio.js +5 -8
  39. package/tiledeskChatbotPlugs/directives/DirDeflectToHelpCenter.js +11 -1
  40. package/tiledeskChatbotPlugs/directives/DirDepartment.js +15 -6
  41. package/tiledeskChatbotPlugs/directives/DirFireTiledeskEvent.js +17 -6
  42. package/tiledeskChatbotPlugs/directives/DirForm.js +12 -2
  43. package/tiledeskChatbotPlugs/directives/DirGptTask.js +83 -38
  44. package/tiledeskChatbotPlugs/directives/DirGptTask_OLD.js +4 -7
  45. package/tiledeskChatbotPlugs/directives/DirHubspot.js +5 -8
  46. package/tiledeskChatbotPlugs/directives/DirIfOnlineAgents.js +14 -27
  47. package/tiledeskChatbotPlugs/directives/DirIfOnlineAgentsV2.js +278 -0
  48. package/tiledeskChatbotPlugs/directives/DirIfOpenHours.js +147 -51
  49. package/tiledeskChatbotPlugs/directives/DirIfOpenHours_OLD.js +125 -0
  50. package/tiledeskChatbotPlugs/directives/DirIntent.js +8 -37
  51. package/tiledeskChatbotPlugs/directives/DirJSONCondition.js +5 -26
  52. package/tiledeskChatbotPlugs/directives/DirMessage.js +19 -17
  53. package/tiledeskChatbotPlugs/directives/DirMessageToBot.js +135 -0
  54. package/tiledeskChatbotPlugs/directives/DirMoveToAgent.js +20 -87
  55. package/tiledeskChatbotPlugs/directives/DirMoveToUnassigned.js +59 -0
  56. package/tiledeskChatbotPlugs/directives/DirQapla.js +6 -9
  57. package/tiledeskChatbotPlugs/directives/DirRandomReply.js +17 -7
  58. package/tiledeskChatbotPlugs/directives/DirRemoveCurrentBot.js +17 -7
  59. package/tiledeskChatbotPlugs/directives/DirReplaceBot.js +11 -2
  60. package/tiledeskChatbotPlugs/directives/DirReplaceBotV2.js +135 -21
  61. package/tiledeskChatbotPlugs/directives/DirReplaceBotV3.js +163 -0
  62. package/tiledeskChatbotPlugs/directives/DirReply.js +53 -9
  63. package/tiledeskChatbotPlugs/directives/DirReplyV2.js +347 -0
  64. package/tiledeskChatbotPlugs/directives/DirSendEmail.js +13 -23
  65. package/tiledeskChatbotPlugs/directives/DirSendWhatsapp.js +247 -0
  66. package/tiledeskChatbotPlugs/directives/DirSetAttributeV2.js +202 -15
  67. package/tiledeskChatbotPlugs/directives/DirSetConversationTags.js +13 -4
  68. package/tiledeskChatbotPlugs/directives/DirWait.js +21 -4
  69. package/tiledeskChatbotPlugs/directives/DirWebRequest.js +1 -2
  70. package/tiledeskChatbotPlugs/directives/DirWebRequestV2.js +166 -103
  71. package/tiledeskChatbotPlugs/directives/DirWhatsappByAttribute.js +2 -60
  72. package/tiledeskChatbotPlugs/directives/Directives.js +16 -1
  73. /package/tiledeskChatbotPlugs/directives/{DirOfflineHours.js → DEPRECATED_DirOfflineHours.js} +0 -0
@@ -0,0 +1,347 @@
1
+ const { Filler } = require('../Filler');
2
+ const { TiledeskChatbot } = require('../../models/TiledeskChatbot');
3
+ const { TiledeskChatbotConst } = require('../../models/TiledeskChatbotConst');
4
+ const { TiledeskChatbotUtil } = require('../../models/TiledeskChatbotUtil');
5
+ const { DirIntent } = require("./DirIntent");
6
+ // const { defaultOptions } = require('liquidjs');
7
+ const { DirMessageToBot } = require('./DirMessageToBot');
8
+ const { v4: uuidv4 } = require('uuid');
9
+ const { TiledeskClient } = require('@tiledesk/tiledesk-client');
10
+
11
+ class DirReplyV2 {
12
+
13
+ constructor(context) {
14
+ if (!context) {
15
+ throw new Error('context object is mandatory.');
16
+ }
17
+ this.context = context;
18
+ this.projectId = context.projectId;
19
+ this.requestId = context.requestId;
20
+ this.token = context.token;
21
+ this.tdcache = context.tdcache;
22
+ this.log = context.log;
23
+ this.intentDir = new DirIntent(context);
24
+ this.chatbot = context.chatbot;
25
+ this.reply = context.reply;
26
+ this.originalMessage = context.message;
27
+
28
+ this.API_ENDPOINT = context.API_ENDPOINT;
29
+ this.tdClient = new TiledeskClient({
30
+ projectId: this.context.projectId,
31
+ token: this.context.token,
32
+ APIURL: this.API_ENDPOINT,
33
+ APIKEY: "___",
34
+ log: this.log
35
+ });
36
+ }
37
+
38
+ execute(directive, callback) {
39
+ let action;
40
+ if (directive.action) {
41
+ action = directive.action;
42
+ if (!action.attributes) {
43
+ action.attributes = {}
44
+ }
45
+ action.attributes.fillParams = true;
46
+ }
47
+ else {
48
+ console.error("Incorrect directive (no action provided):", directive);
49
+ callback();
50
+ return;
51
+ }
52
+ this.go(action, (stop) => {
53
+ callback(stop);
54
+ });
55
+ }
56
+
57
+ async go(action, callback) {
58
+ if (this.log) { console.log("ReplyV2 action!", JSON.stringify(action)); }
59
+ const message = action;
60
+
61
+ let current; // debug only
62
+ if (this.log) {
63
+ if (message.attributes.commands[1].message.text) {
64
+ current = message.attributes.commands[1].message.text
65
+ }
66
+ console.log("current:", current);
67
+ }
68
+ let must_stop = false;
69
+ // fill
70
+ let requestAttributes = null;
71
+ if (this.tdcache) {
72
+ requestAttributes =
73
+ await TiledeskChatbot.allParametersStatic(
74
+ this.tdcache, this.requestId
75
+ );
76
+ if (this.log) {
77
+ for (const [key, value] of Object.entries(requestAttributes)) {
78
+ const value_type = typeof value;
79
+ }
80
+ }
81
+
82
+ try {
83
+ // lock/unlock + no-match
84
+ // get buttons if available
85
+ const buttons = TiledeskChatbotUtil.allReplyButtons(message);
86
+ if (this.log) { console.log("Action Buttons:", JSON.stringify(buttons)); }
87
+ if (buttons && buttons.length > 0) {
88
+ const locked = await this.lockUnlock(action); // first execution returns locked, then unlocked
89
+ if (locked) { // fist execution returns (just) locked
90
+ if (this.log) { console.log("first time pass!"); }
91
+ must_stop = true; // you must stop after next callbacks (in this flow) if there are buttons
92
+ // console.log("action:", action);
93
+ if (action.noInputIntent) {
94
+ if (this.log) { console.log("NoInputIntent found:", action.noInputIntent); }
95
+ const noInputIntent = action.noInputIntent;
96
+ const noInputTimeout = action.noInputTimeout;
97
+ if (this.log) { console.log("noInputTimeout found:", noInputTimeout); }
98
+ if (noInputTimeout > 0 && noInputTimeout < 7776000) {
99
+ const timeout_id = uuidv4();
100
+ await this.chatbot.addParameter(TiledeskChatbotConst.USER_INPUT, timeout_id); // control variable. On each user input is removed
101
+ if (this.log) { console.log("Set userInput: false, checking...", await this.chatbot.getParameter(TiledeskChatbotConst.USER_INPUT)); }
102
+ setTimeout(async () => {
103
+ if (this.log) { console.log("noinput timeout triggered!"); }
104
+ const userInput = await this.chatbot.getParameter(TiledeskChatbotConst.USER_INPUT);
105
+ if (this.log) { console.log("got 'userInput':", userInput); }
106
+ if (userInput && userInput === timeout_id) {
107
+ if (this.log) { console.log("no 'userInput'. Executing noinput action:", noInputIntent); }
108
+ await this.chatbot.unlockIntent(this.requestId);
109
+ await this.chatbot.unlockAction(this.requestId);
110
+ if (this.log) { console.log("unlocked (for noInput) ReplyV2"); }
111
+ let noinput_action = DirIntent.intentDirectiveFor(noInputIntent, null);
112
+ this.intentDir.execute(noinput_action, () => {
113
+ if (this.log) { console.log("noinput action invoked", noinput_action); }
114
+ });
115
+ }
116
+ else {
117
+ if (this.log) { console.log("skipping noinput action because of userInput", userInput); }
118
+ }
119
+ }, noInputTimeout);
120
+ }
121
+ }
122
+ }
123
+ else { // second execution
124
+ if (this.log) { console.log("second pass! unlocked!"); }
125
+ const last_user_text = await this.chatbot.getParameter(TiledeskChatbotConst.REQ_LAST_USER_TEXT_v2_KEY);
126
+ if (this.log) { console.log("got last user text"); }
127
+ const button = TiledeskChatbotUtil.buttonByText(last_user_text, buttons);
128
+ if (this.log) { console.log("button found", JSON.stringify(button)); }
129
+ // invoke button
130
+ if (button && button.action) {
131
+ if (this.log) { console.log("moving to button action", button.action); }
132
+ let button_action = DirIntent.intentDirectiveFor(button.action, null);
133
+ if (this.log) { console.log("action with .intentName:", button_action); }
134
+ this.intentDir.execute(button_action, () => {
135
+ if (this.log) { console.log("action invoked", button_action); }
136
+ });
137
+ if (this.log) { console.log("callback(true) + return", current); }
138
+ callback(true); // must_stop = true
139
+ return;
140
+ }
141
+ else { // no match (treating text buttons as no-match for the moment)
142
+ // if noMatchIntent invoke
143
+ // const button = TiledeskChatbotUtil.buttonByText("nomatch", buttons);
144
+ if (this.log) { console.log("nomatch button found", JSON.stringify(button)); }
145
+ // // invoke button
146
+ // if (button && button.action) {
147
+ // console.log("moving to nomatch action", button.action);
148
+ // let button_action = DirIntent.intentDirectiveFor(button.action, null);
149
+ // this.intentDir.execute(button_action, () => {
150
+ // console.log("nomatch action invoked", button_action);
151
+ // });
152
+ // console.log("callback(true) + return 2", current);
153
+ // callback(true);
154
+ // return;
155
+ // }
156
+ if (action.noMatchIntent) {
157
+ if (this.log) { console.log("moving to nomatch action", action.noMatchIntent); }
158
+ let nomatch_action = DirIntent.intentDirectiveFor(action.noMatchIntent, null);
159
+ this.intentDir.execute(nomatch_action, () => {
160
+ if (this.log) { console.log("nomatch action invoked", nomatch_action); }
161
+ });
162
+ if (this.log) { console.log("callback(true) + return no-match", current); }
163
+ callback(true); // must_stop = true
164
+ return;
165
+ }
166
+ else {
167
+ // const defaultFallbackAction = { action: { intentName: "defaultFallback" } };
168
+
169
+ // console.log("re-send original message:",JSON.stringify(this.originalMessage));
170
+ const messageDir = new DirMessageToBot(this.context);
171
+ messageDir.execute( { action: { message: this.originalMessage } }, () => {
172
+ if (this.log) { console.log("messageDir invoked"); }
173
+ });
174
+ if (this.log) { console.log("callback(true) + return no-match", current); }
175
+ callback(true); // must_stop = true
176
+ return;
177
+
178
+ // const textAction = { action: { text: last_user_text } };
179
+ // console.log("textAction invoked:",textAction ); //, defaultFallbackAction);
180
+ // this.intentDir.execute( textAction, () => {
181
+ // if (this.log) { console.log("textAction invoked", textAction); }
182
+ // });
183
+ // if (this.log) { console.log("callback(true) + return no-match", current); }
184
+ // callback(true); // must_stop = true
185
+ // return;
186
+
187
+
188
+ // // there is no "no-match", go on...
189
+ // if (this.log) { console.log("callback(false) + return 3", current); }
190
+ // callback(false);
191
+ // return;
192
+ }
193
+ }
194
+ }
195
+ }
196
+ }
197
+ catch(error) {
198
+ console.error("Error in DirReplyV2:", error);
199
+ }
200
+
201
+
202
+ if (this.log) { console.log("proceding normally to render and send the reply", current); }
203
+ const filler = new Filler();
204
+ // fill text attribute
205
+ message.text = filler.fill(message.text, requestAttributes);
206
+ if (message.metadata) {
207
+ if (this.log) {console.log("filling message 'metadata':", JSON.stringify(message.metadata));}
208
+ if (message.metadata.src) {
209
+ message.metadata.src = filler.fill(message.metadata.src, requestAttributes);
210
+ }
211
+ if (message.metadata.name) {
212
+ message.metadata.name = filler.fill(message.metadata.name, requestAttributes);
213
+ }
214
+ }
215
+ if (this.log) {console.log("filling commands'. Message:", JSON.stringify(message));}
216
+ if (message.attributes && message.attributes.commands) {
217
+ if (this.log) {console.log("filling commands'. commands found.");}
218
+ let commands = message.attributes.commands;
219
+ if (this.log) {console.log("commands:", JSON.stringify(commands), commands.length);}
220
+ if (commands.length > 0) {
221
+ if (this.log) {console.log("commands' found");}
222
+ for (let i = 0; i < commands.length; i++) {
223
+ let command = commands[i];
224
+ if (command.type === 'message' && command.message && command.message.text) {
225
+ command.message.text = filler.fill(command.message.text, requestAttributes);
226
+ TiledeskChatbotUtil.fillCommandAttachments(command, requestAttributes, this.log);
227
+ if (this.log) {console.log("command filled:", command.message.text);}
228
+ }
229
+ }
230
+ }
231
+ }
232
+
233
+ // EVALUATE EXPRESSION AND REMOVE BASED ON EVALUATION
234
+ if (this.log) {console.log("message before filters:", JSON.stringify(message));}
235
+ if (message.attributes && message.attributes.commands) {
236
+ if (this.log) {console.log("filterOnVariables...on commands", JSON.stringify(message.attributes.commands));}
237
+ if (this.log) {console.log("filterOnVariables...on attributes", requestAttributes);}
238
+ // TiledeskChatbotUtil.filterOnVariables(message.attributes.commands, requestAttributes);
239
+ TiledeskChatbotUtil.filterOnVariables(message, requestAttributes);
240
+ }
241
+
242
+ // temporary send back of reserved attributes
243
+ if (!message.attributes) {
244
+ message.attributes = {}
245
+ }
246
+ // Reserved names: userEmail, userFullname
247
+ // if (requestAttributes['userEmail']) {
248
+ // message.attributes.updateUserEmail = requestAttributes['userEmail'];
249
+ // }
250
+ // if (requestAttributes['userFullname']) {
251
+ // message.attributes.updateUserFullname = requestAttributes['userFullname'];
252
+ // }
253
+ // intent_info
254
+ if (this.context.reply && this.context.reply.attributes && this.context.reply.attributes.intent_info) {
255
+ message.attributes.intentName = this.context.reply.attributes.intent_info.intent_name;
256
+ }
257
+ // userFlowAttributes
258
+ let userFlowAttributes = TiledeskChatbotUtil.userFlowAttributes(requestAttributes);
259
+ if (this.log) { console.log("userFlowAttributes:", userFlowAttributes); }
260
+ if (userFlowAttributes) {
261
+ message.attributes["flowAttributes"] = {};
262
+ for (const [key, value] of Object.entries(userFlowAttributes)) {
263
+ try {
264
+ if(typeof value === 'string' && value.length <= 1000){
265
+ message.attributes["flowAttributes"][key] = value;
266
+ }
267
+ }
268
+ catch(err) {
269
+ console.error("An error occurred while JSON.parse(). Parsed value:" + value + " in allParametersStatic(). Error:", err);
270
+ }
271
+ }
272
+ }
273
+
274
+ }
275
+ // send!
276
+ let cleanMessage = message;
277
+ // cleanMessage = TiledeskChatbotUtil.removeEmptyReplyCommands(message);
278
+ // if (!TiledeskChatbotUtil.isValidReply(cleanMessage)) {
279
+ // console.log("invalid message", cleanMessage);
280
+ // callback(); // cancel reply operation
281
+ // return;
282
+ // }
283
+ // console.log("valid message!", cleanMessage);
284
+ cleanMessage.senderFullname = this.context.chatbot.bot.name;
285
+ if (this.log) {console.log("Reply:", JSON.stringify(cleanMessage))};
286
+ await TiledeskChatbotUtil.updateConversationTranscript(this.context.chatbot, cleanMessage);
287
+ this.tdClient.sendSupportMessage(
288
+ this.requestId,
289
+ cleanMessage,
290
+ (err) => {
291
+ if (err) {
292
+ console.error("Error sending reply:", err);
293
+ }
294
+ if (this.log) {console.log("Reply message sent");}
295
+ const delay = TiledeskChatbotUtil.totalMessageWait(cleanMessage);
296
+ // console.log("got total delay:", delay)
297
+ if (delay > 0 && delay <= 30000) { // prevent long delays
298
+ if (this.log) { console.log("start timeout callback(" + must_stop + ") for:", current); }
299
+ setTimeout(async () => {
300
+ if (this.log) { console.log("callback(" + must_stop + ") after delay", current); }
301
+ callback(must_stop);
302
+ }, delay);
303
+ }
304
+ else {
305
+ // console.log("invalid delay.")
306
+ callback(must_stop);
307
+ }
308
+ });
309
+
310
+ }
311
+
312
+
313
+ async lockUnlock(action, callback) {
314
+ let lockedAction = await this.chatbot.currentLockedAction(this.requestId);
315
+ // console.log("(DirReplyV2) lockedAction:", lockedAction);
316
+ if (!lockedAction) {
317
+ // console.log("(DirReplyV2) !lockedAction");
318
+ const intent_name = this.reply.attributes.intent_info.intent_name
319
+ const actionId = action["_tdActionId"];
320
+ // console.log("(DirReplyV2) intent_name:", intent_name);
321
+ // console.log("(DirReplyV2) actionId:", actionId);
322
+ await this.chatbot.lockIntent(this.requestId, intent_name);
323
+ // console.log("(DirReplyV2) lockIntent");
324
+ await this.chatbot.lockAction(this.requestId, actionId);
325
+ // console.log("(DirReplyV2) lockAction");
326
+ let _lockedAction = await this.chatbot.currentLockedAction(this.requestId);
327
+ let _lockedIntent = await this.chatbot.currentLockedIntent(this.requestId);
328
+ // console.log("(DirReplyV2) _lockedAction", _lockedAction);
329
+ // console.log("(DirReplyV2) _lockedIntent", _lockedIntent);
330
+ // callback();
331
+ return true;
332
+ } else {
333
+ try {
334
+ await this.chatbot.unlockIntent(this.requestId);
335
+ await this.chatbot.unlockAction(this.requestId);
336
+ // console.log("unlocked ReplyV2");
337
+ return false;
338
+ }
339
+ catch(e) {
340
+ console.error("Error", e);
341
+ }
342
+ }
343
+ }
344
+
345
+ }
346
+
347
+ module.exports = { DirReplyV2 };
@@ -2,6 +2,7 @@ const { param } = require('express/lib/request');
2
2
  const ms = require('minimist-string');
3
3
  const { TiledeskChatbot } = require('../../models/TiledeskChatbot');
4
4
  const { Filler } = require('../Filler');
5
+ const { TiledeskClient } = require('@tiledesk/tiledesk-client');
5
6
  // const { TiledeskClient } = require('@tiledesk/tiledesk-client');
6
7
 
7
8
  class DirSendEmail {
@@ -11,29 +12,18 @@ class DirSendEmail {
11
12
  throw new Error('context object is mandatory.');
12
13
  }
13
14
  this.context = context;
14
- this.tdclient = context.tdclient;
15
15
  this.tdcache = context.tdcache;
16
16
  this.requestId = context.requestId;
17
- this.log = context.log;
18
- // let context = {
19
- // projectId: projectId,
20
- // token: token,
21
- // supportRequest: supportRequest,
22
- // requestId: supportRequest.request_id,
23
- // TILEDESK_APIURL: API_URL,
24
- // TILEBOT_ENDPOINT:TILEBOT_ENDPOINT,
25
- // departmentId: depId,
26
- // tdcache: tdcache,
27
- // log: false
28
- // }
29
- // this.tdclient = new TiledeskClient({
30
- // projectId: context.projectId,
31
- // token: context.token,
32
- // APIURL: context.TILEDESK_APIURL,
33
- // APIKEY: "___",
34
- // log: context.log
35
- // });
36
-
17
+ this.log = context.log;
18
+
19
+ this.API_ENDPOINT = context.API_ENDPOINT;
20
+ this.tdClient = new TiledeskClient({
21
+ projectId: this.context.projectId,
22
+ token: this.context.token,
23
+ APIURL: this.API_ENDPOINT,
24
+ APIKEY: "___",
25
+ log: this.log
26
+ });
37
27
  }
38
28
 
39
29
  execute(directive, callback) {
@@ -82,8 +72,8 @@ class DirSendEmail {
82
72
  to: filled_to,
83
73
  replyto: reply_to
84
74
  }
85
- console.log("email message:", JSON.stringify(message));
86
- const message_echo = await this.tdclient.sendEmail(message);
75
+ // console.log("email message:", JSON.stringify(message));
76
+ const message_echo = await this.tdClient.sendEmail(message);
87
77
  if (this.log) {console.log("email sent. filled_subject:", filled_subject);}
88
78
  if (this.log) {console.log("email sent. filled_text:", filled_text);}
89
79
  if (this.log) {console.log("email sent. filled_to:", filled_to);}
@@ -0,0 +1,247 @@
1
+ const axios = require("axios").default;
2
+ const { TiledeskChatbot } = require('../../models/TiledeskChatbot');
3
+ const { Filler } = require("../Filler");
4
+ const { DirIntent } = require("./DirIntent");
5
+
6
+ let whatsapp_api_url;
7
+
8
+ class DirSendWhatsapp {
9
+
10
+ constructor(context) {
11
+ if (!context) {
12
+ throw new Error('context object is mandatory');
13
+ }
14
+ this.context = context;
15
+ this.chatbot = context.chatbot;
16
+ this.tdcache = this.context.tdcache;
17
+ this.requestId = this.context.requestId;
18
+ this.intentDir = new DirIntent(context);
19
+ this.API_ENDPOINT = this.context.API_ENDPOINT;
20
+ this.log = context.log;
21
+ }
22
+
23
+ execute(directive, callback) {
24
+ if (this.log) { console.log("DirWhatsappStatic directive: ", directive); }
25
+ let action;
26
+ if (directive.action) {
27
+ action = directive.action;
28
+ }
29
+ else {
30
+ console.error("Incorrect directive: ", JSON.stringify(directive));
31
+ callback();
32
+ return;
33
+ }
34
+ this.go(action, (stop) => {
35
+ callback(stop);
36
+ })
37
+ }
38
+
39
+ async go(action, callback) {
40
+
41
+ if (this.log) { console.log("DirWhatsappStatic action: ", JSON.stringify(action)) }
42
+ if (!this.tdcache) {
43
+ console.error("Error: DirAskGPT tdcache is mandatory");
44
+ callback();
45
+ return;
46
+ }
47
+
48
+ let trueIntent = action.trueIntent;
49
+ let falseIntent = action.falseIntent;
50
+
51
+ let requestVariables = null;
52
+ requestVariables =
53
+ await TiledeskChatbot.allParametersStatic(
54
+ this.tdcache, this.requestId
55
+ )
56
+
57
+ // Declarations
58
+ let payload = action.payload;
59
+
60
+ const filler = new Filler();
61
+
62
+ // receiver_list will be of just one element, so we can pick up only the first element, if exists.
63
+ let receiver = payload.receiver_list[0];
64
+
65
+
66
+ //header_params: text, image, document. NO: location
67
+ //body_params: text
68
+ //button_params: text
69
+ //footer_paramas: non supportati
70
+
71
+ receiver = await this.fillWholeReceiver(receiver, requestVariables);
72
+ payload.receiver_list[0] = receiver;
73
+ payload.transaction_id = this.context.requestId;
74
+ payload.broadcast = false;
75
+
76
+ const whatsapp_api_url_pre = process.env.WHATSAPP_ENDPOINT;
77
+
78
+ if (whatsapp_api_url_pre) {
79
+ whatsapp_api_url = whatsapp_api_url_pre;
80
+ } else {
81
+ whatsapp_api_url = this.API_ENDPOINT + "/modules/whatsapp/api"
82
+ }
83
+ if (this.log) { console.log("DirSendWhatsapp whatsapp_api_url: ", whatsapp_api_url); };
84
+
85
+ const HTTPREQUEST = {
86
+ url: whatsapp_api_url + "/tiledesk/broadcast",
87
+ headers: {
88
+ 'Content-Type': 'application/json'
89
+ },
90
+ json: payload,
91
+ method: 'POST'
92
+ }
93
+
94
+ if (this.log) { console.log("DirSendWhatsapp HTTPREQUEST: ", HTTPREQUEST); }
95
+
96
+ this.#myrequest(
97
+ HTTPREQUEST, async (err, resbody) => {
98
+ if (err) {
99
+ console.error("DirSendWhatsapp error: ", err);
100
+ await this.chatbot.addParameter("flowError", "SendWhatsapp Error: " + err);
101
+ if (callback) {
102
+ if (falseIntent) {
103
+ await this.#executeCondition(false, trueIntent, null, falseIntent, null);
104
+ callback(true);
105
+ return;
106
+ }
107
+ callback();
108
+ return;
109
+ }
110
+ } else if (resbody.success === true) {
111
+ if (callback) {
112
+ if (trueIntent) {
113
+ await this.#executeCondition(true, trueIntent, null, falseIntent, null);
114
+ callback(true);
115
+ return;
116
+ }
117
+ callback();
118
+ return;
119
+ }
120
+ } else {
121
+ if (this.log) { console.log("DirSendWhatsapp unexpected resbody: ", resbody); }
122
+ if (callback) {
123
+ if (falseIntent) {
124
+ await this.#executeCondition(false, trueIntent, null, falseIntent, null);
125
+ callback(true);
126
+ return
127
+ }
128
+ callback();
129
+ return;
130
+ }
131
+ }
132
+ }
133
+ )
134
+ }
135
+
136
+ async #executeCondition(result, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, callback) {
137
+ let trueIntentDirective = null;
138
+ if (trueIntent) {
139
+ trueIntentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
140
+ }
141
+ let falseIntentDirective = null;
142
+ if (falseIntent) {
143
+ falseIntentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
144
+ }
145
+ if (result === true) {
146
+ if (trueIntentDirective) {
147
+ this.intentDir.execute(trueIntentDirective, () => {
148
+ if (callback) {
149
+ callback();
150
+ }
151
+ })
152
+ }
153
+ else {
154
+ if (this.log) { console.log("No trueIntentDirective specified"); }
155
+ if (callback) {
156
+ callback();
157
+ }
158
+ }
159
+ }
160
+ else {
161
+ if (falseIntentDirective) {
162
+ this.intentDir.execute(falseIntentDirective, () => {
163
+ if (callback) {
164
+ callback();
165
+ }
166
+ });
167
+ }
168
+ else {
169
+ if (this.log) { console.log("No falseIntentDirective specified"); }
170
+ if (callback) {
171
+ callback();
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ async fillWholeReceiver(receiver, requestVariables) {
178
+ return new Promise((resolve) => {
179
+
180
+ const filler = new Filler();
181
+ try {
182
+ receiver.phone_number = filler.fill(receiver.phone_number, requestVariables);
183
+ if (receiver.header_params) {
184
+ receiver.header_params.forEach(p => {
185
+ if (p.type === 'TEXT') {
186
+ p.text = filler.fill(p.text, requestVariables)
187
+ }
188
+ else if (p.type === 'IMAGE') {
189
+ p.image.link = filler.fill(p.image.link, requestVariables)
190
+ }
191
+ else if (p.type === 'DOCUMENT') {
192
+ p.document.link = filler.fill(p.document.link, requestVariables)
193
+ }
194
+ })
195
+ }
196
+
197
+ if (receiver.body_params) {
198
+ receiver.body_params.forEach(p => {
199
+ p.text = filler.fill(p.text, requestVariables)
200
+ })
201
+ }
202
+
203
+ if (receiver.buttons_params) {
204
+ receiver.buttons_params.forEach(p => {
205
+ p.text = filler.fill(p.text, requestVariables)
206
+ })
207
+ }
208
+
209
+ resolve(receiver);
210
+
211
+ } catch(err) {
212
+ console.error("DirSendWhatsapp fillWholeReceiver error: ", err)
213
+ resolve(null);
214
+ }
215
+
216
+ })
217
+ }
218
+
219
+ // HTTP REQUEST
220
+ async #myrequest(options, callback, log) {
221
+ return await axios({
222
+ url: options.url,
223
+ method: options.method,
224
+ data: options.json,
225
+ params: options.params,
226
+ headers: options.headers
227
+ }).then((res) => {
228
+ if (res && res.status == 200 && res.data) {
229
+ if (callback) {
230
+ callback(null, res.data);
231
+ }
232
+ }
233
+ else {
234
+ if (callback) {
235
+ callback(TiledeskClient.getErr({ message: "Response status not 200" }, options, res), null, null);
236
+ }
237
+ }
238
+ }).catch((err) => {
239
+ console.error("(tybot request) An error occured: ", err);
240
+ if (callback) {
241
+ callback(err, null, null);
242
+ }
243
+ })
244
+ }
245
+ }
246
+
247
+ module.exports = { DirSendWhatsapp }