@tiledesk/tiledesk-tybot-connector 2.0.35 → 2.0.36-rc12

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.
@@ -43,48 +43,60 @@ class TiledeskChatbot {
43
43
  }
44
44
 
45
45
  async replyToMessage(message, callback) {
46
+ console.log(`(GAB) TiledeskChatbot replyToMessage start --> at : ${new Date().getTime()} for message.sender: ${message.sender} with text: ${message.text}`)
46
47
  return new Promise( async (resolve, reject) => {
47
48
  let lead = null;
48
49
  if (message.request) {
49
50
  this.request = message.request;
50
51
  }
51
52
 
52
- // reset lockedIntent on direct user invocation ( /intent or action => this only?)
53
+
54
+ let start00 = new Date();
53
55
  if (message.sender != "_tdinternal") {
54
56
  try {
55
- winston.verbose("(TiledeskChatbot) Checking locked intent reset on action invocation")
56
- if (message.attributes && message.attributes.action) {
57
- winston.debug("(TiledeskChatbot) Message has action: " + message.attributes.action)
58
- await this.unlockIntent(this.requestId);
59
- await this.unlockAction(this.requestId);
60
- winston.debug("(TiledeskChatbot) Reset locked intent. Intent was explicitly invoked with an action: " + message.attributes.action)
57
+ winston.verbose("(TiledeskChatbot) External user message, running reset operations…");
58
+ const ops = [];
59
+
60
+ // --- Action/intent reset ---
61
+ // reset lockedIntent on direct user invocation ( /intent or action => this only?)
62
+ if (message.attributes?.action) {
63
+ winston.debug("(TiledeskChatbot) Message has action: " + message.attributes.action);
64
+ ops.push(this.unlockIntent(this.requestId), this.unlockAction(this.requestId));
65
+ winston.debug("(TiledeskChatbot) Reset locked intent. Intent was explicitly invoked with an action: " + message.attributes.action);
61
66
  }
62
- } catch(error) {
63
- winston.error("(TiledeskChatbot) Error resetting locked intent: ", error)
64
- }
65
- }
66
67
 
67
- // any external invocation restarts the steps counter
68
- try {
69
- if (message.sender != "_tdinternal") {
68
+ // --- Steps reset ---
69
+ // any external invocation restarts the steps counter
70
70
  winston.verbose("(TiledeskChatbot) Resetting current step by request message: " + message.text);
71
- await TiledeskChatbot.resetStep(this.tdcache, this.requestId);
72
- await TiledeskChatbot.resetStarted(this.tdcache, this.requestId);
71
+ ops.push(
72
+ TiledeskChatbot.resetStep(this.tdcache, this.requestId),
73
+ TiledeskChatbot.resetStarted(this.tdcache, this.requestId)
74
+ );
73
75
 
76
+ await Promise.all(ops);
77
+
78
+ // --- Debug final state ---
74
79
  if (this.tdcache) {
75
- let currentStep =
76
- await TiledeskChatbot.currentStep(this.tdcache, this.requestId);
80
+ const currentStep = await TiledeskChatbot.currentStep(this.tdcache, this.requestId);
77
81
  winston.verbose("(TiledeskChatbot) After reset currentStep:" + currentStep);
78
82
  }
79
-
83
+
84
+ } catch (error) {
85
+ winston.error("(TiledeskChatbot) Error resetting locked intent: ", error)
80
86
  }
81
- } catch(error) {
82
- winston.error("(TiledeskChatbot) Error resetting locked intent: ", error);
83
87
  }
88
+ let end00 = new Date()
89
+ console.log(`(GAB) TiledeskChatbot replyToMessage 00--> after reset lockedIntent at : ${end00.getTime()}, diff: ${end00-start00}[ms]`)
90
+
91
+
84
92
 
85
93
  // Checking locked intent (for non-internal intents)
86
94
  // internal intents always "skip" the locked intent
95
+ let start0 = new Date()
87
96
  const locked_intent = await this.currentLockedIntent(this.requestId);
97
+ let end0 = new Date()
98
+ console.log(`(GAB) TiledeskChatbot replyToMessage 0--> after currentLockedIntent at : ${end0.getTime()}, diff: ${end0-start0}[ms]`)
99
+
88
100
  winston.verbose("(TiledeskChatbot) Got locked intent: -" + locked_intent + "-");
89
101
  if (locked_intent) {
90
102
  // const tdclient = new TiledeskClient({
@@ -95,11 +107,18 @@ class TiledeskChatbot {
95
107
  // });
96
108
  // it only gets the locked_intent
97
109
  // const faq = await this.botsDataSource.getByIntentDisplayName(this.botId, locked_intent);
110
+ let start0 = new Date()
98
111
  const faq = await this.botsDataSource.getByIntentDisplayNameCache(this.botId, locked_intent, this.tdcache);
112
+ let end0 = new Date()
113
+ console.log(`(GAB) TiledeskChatbot replyToMessage 1-> after botsDataSource.getByIntentDisplayNameCache at : ${end0.getTime()}, diff: ${end0-start0}[ms]`)
99
114
  winston.debug("(TiledeskChatbot) Locked intent. Got faqs: ", faq);
100
115
  let reply;
101
116
  if (faq) {
117
+ let start1 = new Date()
102
118
  reply = await this.execIntent(faq, message, lead);//, bot);
119
+ let end1 = new Date()
120
+ console.log(`(GAB) TiledeskChatbot replyToMessage 1--> after execIntent at : ${end1.getTime()}, diff: ${end1-start1}[ms]`)
121
+
103
122
  }
104
123
  else {
105
124
  reply = {
@@ -148,7 +167,10 @@ class TiledeskChatbot {
148
167
  }
149
168
  else {
150
169
  winston.verbose("(TiledeskChatbot) Processing intent:", explicit_intent_name)
170
+ let start2 = new Date()
151
171
  let faq = await this.botsDataSource.getByIntentDisplayNameCache(this.botId, intent.name, this.tdcache);
172
+ let end2 = new Date()
173
+ console.log(`(GAB) TiledeskChatbot replyToMessage 2--> after botsDataSource.getByIntentDisplayNameCache at : ${end2.getTime()}, diff: ${end2-start2}[ms]`)
152
174
  if (faq) {
153
175
  winston.verbose("(TiledeskChatbot) Got a reply (faq) by Intent name:", faq)
154
176
  try {
@@ -158,7 +180,11 @@ class TiledeskChatbot {
158
180
  this.addParameter(key, value);
159
181
  }
160
182
  }
183
+ let start2 = new Date();
161
184
  reply = await this.execIntent(faq, message, lead);
185
+ let end2 = new Date()
186
+ console.log(`(GAB) TiledeskChatbot replyToMessage 2--> after execIntent at : ${end2.getTime()}, diff: ${end2-start2}[ms]`)
187
+
162
188
  resolve(reply);
163
189
  return;
164
190
  }
@@ -189,7 +215,11 @@ class TiledeskChatbot {
189
215
  let reply;
190
216
  const faq = faqs[0];
191
217
  try {
218
+ let start3 = new Date();
192
219
  reply = await this.execIntent(faq, message, lead);//, bot);
220
+ let end3 = new Date()
221
+ console.log(`(GAB) TiledeskChatbot replyToMessage 3--> after execIntent at : ${end3.getTime()}, diff: ${end3-start3}[ms]`)
222
+
193
223
  }
194
224
  catch(error) {
195
225
  winston.error("(TiledeskChatbot) An error occured during exact match execIntent(): ", error);
@@ -217,10 +247,18 @@ class TiledeskChatbot {
217
247
  }
218
248
  winston.debug("(TiledeskChatbot) NLP intents found: ", intents);
219
249
  if (intents && intents.length > 0) {
250
+ let start2 = new Date();
220
251
  let faq = await this.botsDataSource.getByIntentDisplayNameCache(this.botId, intents[0].intent_display_name, this.tdcache);
252
+ let end2 = new Date()
253
+ console.log(`(GAB) TiledeskChatbot replyToMessage 4--> after botsDataSource.getByIntentDisplayNameCache in if at : ${end2.getTime()}, diff: ${end2-start2}[ms]`)
254
+
221
255
  let reply;
222
256
  try {
257
+ let start3 = new Date();
223
258
  reply = await this.execIntent(faq, message, lead);//, bot);
259
+ let end3 = new Date()
260
+ console.log(`(GAB) TiledeskChatbot replyToMessage 4--> after execIntent in if at : ${end3.getTime()}, diff: ${end3-start3}[ms]`)
261
+
224
262
  }
225
263
  catch(error) {
226
264
  winston.error("(TiledeskChatbot) An error occurred during NLP decoding: ", error);
@@ -231,7 +269,11 @@ class TiledeskChatbot {
231
269
  return;
232
270
  }
233
271
  else {
272
+ let start4 = new Date();
234
273
  let fallbackIntent = await this.botsDataSource.getByIntentDisplayNameCache(this.botId, "defaultFallback", this.tdcache);
274
+ let end4 = new Date()
275
+ console.log(`(GAB) TiledeskChatbot replyToMessage 5--> after execIntent in else at : ${end4.getTime()}, diff: ${end4-start4}[ms]`)
276
+
235
277
  if (!fallbackIntent) {
236
278
  resolve(null);
237
279
  return;
@@ -239,7 +281,11 @@ class TiledeskChatbot {
239
281
  else {
240
282
  let reply;
241
283
  try {
284
+ let start5 = new Date()
242
285
  reply = await this.execIntent(fallbackIntent, message, lead);//, bot);
286
+ let end5 = new Date()
287
+ console.log(`(GAB) TiledeskChatbot replyToMessage 5--> after execIntent at : ${end5.getTime()}, diff: ${end5-start5}[ms]`)
288
+
243
289
  }
244
290
  catch(error) {
245
291
  winston.error("(TiledeskChatbot) An error occurred during defaultFallback: ", error);
@@ -40,6 +40,8 @@ class TiledeskChatbotConst {
40
40
  static REQ_LAST_USER_IMAGE_HEIGHT = 'lastUserImageHeight';
41
41
  static REQ_LAST_USER_IMAGE_TYPE = 'lastUserImageType';
42
42
  static REQ_LAST_USER_DOCUMENT_URL = 'lastUserDocumentURL';
43
+ static REQ_LAST_USER_DOCUMENT_AS_ATTACHMENT_URL = 'lastUserDocumentAsAttachmentURL';
44
+ static REQ_LAST_USER_DOCUMENT_AS_INLINE_URL = 'lastUserDocumentAsInlineURL';
43
45
  static REQ_LAST_USER_DOCUMENT_NAME = 'lastUserDocumentName';
44
46
  static REQ_LAST_USER_DOCUMENT_TYPE = 'lastUserDocumentType';
45
47
  static REQ_EMAIL_ATTACHMENTS_LINK = 'link';
package/index.js CHANGED
@@ -43,6 +43,7 @@ let staticBots;
43
43
 
44
44
  router.post('/ext/:botid', async (req, res) => {
45
45
  const botId = req.params.botid;
46
+ console.log(`(GAB) /ext/${botId} 0--> called at : ${new Date().getTime()}`)
46
47
  winston.verbose("(tybotRoute) POST /ext/:botid called: " + botId)
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'"})
@@ -90,6 +91,7 @@ router.post('/ext/:botid', async (req, res) => {
90
91
  {EX: 604800} // 7 days
91
92
  );
92
93
 
94
+ let start0 = new Date()
93
95
  let botsDS;
94
96
  if (!staticBots) {
95
97
  botsDS = new MongodbBotsDataSource({projectId: projectId, botId: botId});
@@ -98,13 +100,20 @@ router.post('/ext/:botid', async (req, res) => {
98
100
  else {
99
101
  botsDS = new MockBotsDataSource(staticBots);
100
102
  }
103
+ let end0 = new Date()
104
+ console.log(`(GAB) /ext/${botId} 1--> after get MongodbBotsDataSource at : ${end0.getTime()}, diff: ${end0-start0}[ms]`)
105
+
101
106
 
102
107
  // get the bot metadata
108
+ let start1 = new Date()
103
109
  let bot = await botsDS.getBotByIdCache(botId, tdcache).catch((err)=> {
104
110
  Promise.reject(err);
105
111
  return;
106
112
  });
113
+ let end1 = new Date()
114
+ console.log(`(GAB) /ext/${botId} 2--> after get botsDS.getBotByIdCache at : ${end1.getTime()}, diff: ${end1-start1}[ms]`)
107
115
 
116
+ let start2 = new Date()
108
117
  let intentsMachine;
109
118
  let backupMachine;
110
119
  if (!staticBots) {
@@ -115,6 +124,8 @@ router.post('/ext/:botid', async (req, res) => {
115
124
  else {
116
125
  intentsMachine = {}
117
126
  }
127
+ let end2 = new Date()
128
+ console.log(`(GAB) /ext/${botId} 3--> after get IntentsMachineFactory.getMachine at : ${end2.getTime()}, diff: ${end2-start2}[ms]`)
118
129
 
119
130
  const chatbot = new TiledeskChatbot({
120
131
  botsDataSource: botsDS,
@@ -133,14 +144,23 @@ router.post('/ext/:botid', async (req, res) => {
133
144
  });
134
145
  winston.verbose("(tybotRoute) Message text: " + message.text)
135
146
 
147
+ let start3 = new Date()
136
148
  await TiledeskChatbotUtil.updateRequestAttributes(chatbot, token, message, projectId, requestId);
149
+ let end3 = new Date()
150
+ console.log(`(GAB) /ext/${botId} 4--> after get TiledeskChatbotUtil.updateRequestAttributes at : ${end3.getTime()}, diff: ${end3-start3}[ms]`)
137
151
  if (requestId.startsWith("support-group-")) {
138
152
  await TiledeskChatbotUtil.updateConversationTranscript(chatbot, message);
139
153
  }
154
+ let end4 = new Date()
155
+ console.log(`(GAB) /ext/${botId} 5--> after get TiledeskChatbotUtil.updateConversationTranscript at : ${end4.getTime()}, diff: ${end4-end3}[ms]`)
156
+
140
157
 
141
158
  let reply = null;
142
159
  try {
160
+ let start5 = new Date()
143
161
  reply = await chatbot.replyToMessage(message);
162
+ let end5 = new Date()
163
+ console.log(`(GAB) /ext/${botId} 6--> after chatbot.replyToMessage at : ${end5.getTime()}, diff: ${end5-start5}[ms]`)
144
164
  }
145
165
  catch(err) {
146
166
  winston.error("(tybotRoute) An error occurred replying to message: ", err);
@@ -151,11 +171,16 @@ router.post('/ext/:botid', async (req, res) => {
151
171
  return;
152
172
  }
153
173
 
174
+
154
175
  if (reply.actions && reply.actions.length > 0) { // structured actions (coming from chatbot designer)
155
176
  try {
177
+ let start6 = new Date()
156
178
  winston.debug("(tybotRoute) Reply actions: ", reply.actions)
157
179
  let directives = TiledeskChatbotUtil.actionsToDirectives(reply.actions);
158
180
  winston.debug("(tybotRoute) the directives:", directives)
181
+ let end6 = new Date()
182
+ console.log(`(GAB) /ext/${botId} 7--> after TiledeskChatbotUtil.actionsToDirectives at : ${end6.getTime()}, diff: ${end6-start6}[ms]`)
183
+
159
184
  let directivesPlug = new DirectivesChatbotPlug(
160
185
  {
161
186
  message: message,
@@ -170,6 +195,7 @@ router.post('/ext/:botid', async (req, res) => {
170
195
  cache: tdcache
171
196
  }
172
197
  );
198
+ console.log(`(GAB) /ext/${botId} 8--> directivesPlug.processDirectives at : ${end6.getTime()}`)
173
199
  directivesPlug.processDirectives( () => {
174
200
  winston.verbose("(tybotRoute) Actions - Directives executed.");
175
201
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-tybot-connector",
3
- "version": "2.0.35",
3
+ "version": "2.0.36-rc12",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -117,6 +117,7 @@ class DirectivesChatbotPlug {
117
117
  }
118
118
 
119
119
  async processDirectives(theend) {
120
+ console.log(`(GAB) DirectivesChatbotPlug 0--> after processDirectives at : ${new Date().getTime()}`)
120
121
  this.theend = theend;
121
122
  const directives = this.directives;
122
123
  if (!directives || directives.length === 0) {
@@ -170,15 +171,23 @@ class DirectivesChatbotPlug {
170
171
  this.curr_directive_index = -1;
171
172
  winston.verbose("(DirectivesChatbotPlug) processing directives...");
172
173
 
174
+ let start1 = new Date()
173
175
  const next_dir = await this.nextDirective(directives);
176
+ let end1 = new Date()
177
+ console.log(`(GAB) DirectivesChatbotPlug 1--> after processDirectives nextDirective at : ${end1.getTime()}, diff: ${end1-start1}[ms]`)
178
+
174
179
  winston.debug("(DirectivesChatbotPlug) next_dir: ", next_dir);
175
180
  await this.process(next_dir);
176
181
  }
177
182
 
178
183
  async nextDirective(directives) {
184
+ console.log(`(GAB) DirectivesChatbotPlug 0--> nextDirective at : ${new Date().getTime()}`)
185
+ let start1 = new Date()
179
186
  winston.debug("(DirectivesChatbotPlug) ....nextDirective() checkStep()");
180
187
  const go_on = await TiledeskChatbot.checkStep(this.context.tdcache, this.context.requestId, this.chatbot?.MAX_STEPS, this.chatbot?.MAX_EXECUTION_TIME);
181
-
188
+ let end1 = new Date()
189
+ console.log(`(GAB) DirectivesChatbotPlug 1--> nextDirective at : ${end1.getTime()}, diff: ${end1-start1}[ms]`)
190
+
182
191
  if (go_on.error) {
183
192
  winston.debug("(DirectivesChatbotPlug) go_on == false! nextDirective() Stopped!");
184
193
  return this.errorMessage(go_on.error); //"Request error: anomaly detection. MAX ACTIONS exeeded.");
@@ -211,6 +220,7 @@ class DirectivesChatbotPlug {
211
220
  }
212
221
 
213
222
  async process(directive) {
223
+ console.log(`(GAB) DirectivesChatbotPlug process 0--> after process at : ${new Date().getTime()}`)
214
224
  let context = this.context;
215
225
  if (directive) {
216
226
  winston.verbose("(DirectivesChatbotPlug) directive['name']: " + directive["name"]);
@@ -219,16 +229,23 @@ class DirectivesChatbotPlug {
219
229
  if (directive && directive.name) {
220
230
  directive_name = directive.name.toLowerCase();
221
231
  }
232
+ let start1 = new Date();
222
233
  if (directive && directive.action) {
223
234
  const action_id = directive.action["_tdActionId"];
224
235
  const locked_action_id = await this.chatbot.currentLockedAction(this.supportRequest.request_id);
236
+ let end1 = new Date()
237
+ console.log(`(GAB) DirectivesChatbotPlug process 1--> after chatbot.currentLockedAction at : ${end1.getTime()}, diff: ${end1-start1}[ms]`)
225
238
  if ( locked_action_id && (locked_action_id !== action_id) ) {
239
+ let start2 = new Date();
226
240
  let next_dir = await this.nextDirective(this.directives);
241
+ let end2 = new Date()
242
+ console.log(`(GAB) DirectivesChatbotPlug process 2--> after chatbot.currentLockedAction at : ${end2.getTime()}, diff: ${end2-start2}[ms]`)
227
243
  this.process(next_dir);
228
244
  return;
229
245
  }
230
246
 
231
247
  }
248
+ let start2 = new Date()
232
249
  if (directive == null || (directive !== null && directive["name"] === undefined)) {
233
250
  winston.debug("(DirectivesChatbotPlug) stop process(). directive is (null?): ", directive);
234
251
  this.theend();
@@ -450,7 +467,11 @@ class DirectivesChatbotPlug {
450
467
  });
451
468
  }
452
469
  else if (directive_name === Directives.WAIT) {
470
+ let end2 = new Date();
471
+ console.log(`(GAB) DirectivesChatbotPlug process 3--> before DirWait execute at : ${end2.getTime()}`)
453
472
  new DirWait(context).execute(directive, async () => {
473
+ let endWait = new Date()
474
+ console.log(`(GAB) DirectivesChatbotPlug process 3--> after DirWait executed callback at : ${endWait.getTime()}, diff: ${endWait-end2}[ms]`)
454
475
  let next_dir = await this.nextDirective(this.directives);
455
476
  this.process(next_dir);
456
477
  });
@@ -18,6 +18,7 @@ class DirWait {
18
18
  }
19
19
 
20
20
  execute(directive, callback) {
21
+ console.log(`(GAB) called DirWait execute at : ${new Date().getTime()}, directive:`, directive)
21
22
  // 500ms < wait-time < 10.000ms
22
23
  winston.verbose("Execute Wait directive");
23
24
  let action;
@@ -47,6 +48,7 @@ class DirWait {
47
48
  }
48
49
 
49
50
  this.go(action, () => {
51
+ console.log(`(DirWait) go callback exit at: ${new Date().getTime()} . . .` )
50
52
  this.logger.native("[Wait] Executed");
51
53
  callback();
52
54
  })
@@ -58,10 +60,16 @@ class DirWait {
58
60
  // const step_key = TiledeskChatbot.requestCacheKey(this.requestId) + ":step";
59
61
  if (action && action.millis >= 1000) {//2000 * 60) { // at list 2 minutes waiting time to reset the steps counter
60
62
  // await this.tdcache.set(step_key, 0);
63
+ let start1= new Date()
61
64
  await TiledeskChatbot.resetStep(this.tdcache, this.requestId);
65
+ let end1 = new Date()
66
+ console.log(`(GAB) called DirWait go() 1-> after TiledeskChatbot.resetStep at : ${end1.getTime()}, diff: ${end1-start1}[ms]`)
67
+
62
68
  }
69
+ console.log(`(GAB) called DirWait go() at :${new Date().getTime()}, millis: ${action.millis}`)
63
70
  this.logger.native("[Wait] Waiting for ", action.millis, "[ms]")
64
71
  setTimeout(() => {
72
+ console.log(`(GAB) called DirWait go() settimeout at : ${new Date().getTime()}`)
65
73
  callback();
66
74
  }, action.millis);
67
75
  }
@@ -680,189 +680,172 @@ class TiledeskChatbotUtil {
680
680
  // update request context
681
681
  try {
682
682
  winston.debug("Updating request variables. Message:", message);
683
- const messageId = message._id;
683
+
684
684
 
685
- if(process.env.BASE_URL){
686
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CHAT_URL, `${process.env.BASE_URL}/dashboard/#/project/${projectId}/wsrequest/${requestId}/messages`);
685
+ const addQueue = [];
686
+ const deleteQueue = [];
687
+ const add = (k, v) => { if (v !== undefined && v !== null && k !== undefined && k !== null) addQueue.push([k, v]); };
688
+ const remove = (k) => { if(k) deleteQueue.push(k);}
689
+
690
+ // --- BASE ATTRIBUTES ---
691
+ if (process.env.BASE_URL) {
692
+ add(TiledeskChatbotConst.REQ_CHAT_URL, `${process.env.BASE_URL}/dashboard/#/project/${projectId}/wsrequest/${requestId}/messages`);
687
693
  }
688
694
 
689
- await chatbot.addParameter(TiledeskChatbotConst.REQ_PROJECT_ID_KEY, projectId);
690
- await chatbot.addParameter(TiledeskChatbotConst.REQ_REQUEST_ID_KEY, requestId);
691
-
695
+ add(TiledeskChatbotConst.REQ_PROJECT_ID_KEY, projectId);
696
+ add(TiledeskChatbotConst.REQ_REQUEST_ID_KEY, requestId);
697
+
698
+ // --- CHATBOT INFO ---
692
699
  if (chatbot.bot) {
693
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CHATBOT_NAME_KEY, chatbot.bot.name);
694
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CHATBOT_ID_KEY, chatbot.bot._id);
695
- }
696
-
697
- if (chatbotToken) {
698
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CHATBOT_TOKEN, chatbotToken); // DEPRECATED
699
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CHATBOT_TOKEN_v2, "JWT " + chatbotToken);
700
+ add(TiledeskChatbotConst.REQ_CHATBOT_NAME_KEY, chatbot.bot.name);
701
+ add(TiledeskChatbotConst.REQ_CHATBOT_ID_KEY, chatbot.bot._id);
700
702
  }
701
-
702
- if (process.env.TILEDESK_API) {
703
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CHATBOT_TOKEN, chatbotToken); // DEPRECATED
704
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CHATBOT_TOKEN_v2, "JWT " + chatbotToken);
703
+
704
+ // --- TOKEN ---
705
+ if (chatbotToken || process.env.TILEDESK_API) {
706
+ add(TiledeskChatbotConst.REQ_CHATBOT_TOKEN, chatbotToken); // deprecated
707
+ add(TiledeskChatbotConst.REQ_CHATBOT_TOKEN_v2, "JWT " + chatbotToken);
705
708
  }
706
-
709
+
707
710
  if (process.env.API_URL) {
708
- await chatbot.addParameter(TiledeskChatbotConst.API_BASE_URL, process.env.API_URL);
711
+ add(TiledeskChatbotConst.API_BASE_URL, process.env.API_URL);
709
712
  }
710
713
 
714
+ // --- USER MESSAGE ---
711
715
  if (message.text && message.sender !== "_tdinternal") {
712
- await chatbot.deleteParameter(TiledeskChatbotConst.USER_INPUT); // user wrote, delete userInput, replyv2 will not trigger timeout action
713
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_TEXT_KEY, message.text); // DEPRECATED
714
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_TEXT_v2_KEY, message.text);
716
+ remove(TiledeskChatbotConst.USER_INPUT); // REAL delete
717
+
718
+ add(TiledeskChatbotConst.REQ_LAST_USER_TEXT_KEY, message.text); // deprecated
719
+ add(TiledeskChatbotConst.REQ_LAST_USER_TEXT_v2_KEY, message.text);
720
+
721
+ add(TiledeskChatbotConst.REQ_LAST_USER_MESSAGE_TYPE_KEY, message.type);
722
+ add(TiledeskChatbotConst.REQ_LAST_USER_MESSAGE_KEY,
723
+ TiledeskChatbotUtil.lastUserMessageFrom(message));
724
+
715
725
  if (message.channel) {
716
- if (message.channel.name === "chat21") {
717
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CHAT_CHANNEL, "web"); // renames the channel in chat21
718
- }
719
- else {
720
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CHAT_CHANNEL, message.channel.name);
721
- }
726
+ const channelName = message.channel.name === "chat21" ? "web" : message.channel.name;
727
+ add(TiledeskChatbotConst.REQ_CHAT_CHANNEL, channelName);
722
728
  }
723
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_MESSAGE_TYPE_KEY, message.type);
724
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_MESSAGE_KEY, TiledeskChatbotUtil.lastUserMessageFrom(message)); // JSON TYPE *NEW
725
729
  }
726
730
 
727
- // get image
728
- if (message.type && message.type === "image" && message.metadata) {
729
- if (message.metadata.src) {
730
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_URL, message.metadata.src);
731
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_NAME, message.metadata.name);
732
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_WIDTH, message.metadata.width);
733
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_HEIGHT, message.metadata.height);
734
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_TYPE, message.metadata.type);
735
- }
731
+ // --- IMAGE ---
732
+ if (message.type && message.type === "image" && message.metadata?.src) {
733
+ add(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_URL, message.metadata.src);
734
+ add(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_NAME, message.metadata.name);
735
+ add(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_WIDTH, message.metadata.width);
736
+ add(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_HEIGHT, message.metadata.height);
737
+ add(TiledeskChatbotConst.REQ_LAST_USER_IMAGE_TYPE, message.metadata.type);
736
738
  }
737
739
 
738
- // get document
739
- if (message.type && message.type === "file" && message.metadata) {
740
- if (message.metadata.src) {
741
- await chatbot.addParameter("lastUserDocumentURL", message.metadata.src); // legacy. will be deprecated
742
- const url_as_attachment = message.metadata.src;
743
- await chatbot.addParameter("lastUserDocumentAsAttachmentURL", url_as_attachment);
744
- let url_inline = url_as_attachment;
745
- if (url_as_attachment.match(/.*\/download.*/)) { // removing "/download" removes the "Content-disposion: attachment" HTTP header
746
- url_inline = url_as_attachment.replace('/download', '/');
747
- }
748
- await chatbot.addParameter("lastUserDocumentAsInlineURL", url_inline);
749
- await chatbot.addParameter("lastUserDocumentName", message.metadata.name);
750
- await chatbot.addParameter("lastUserDocumentType", message.metadata.type);
740
+ // --- DOCUMENT ---
741
+ if (message.type && message.type === "file" && message.metadata?.src) {
742
+
743
+
744
+ if (message.metadata.src) {
745
+ const m = message.metadata;
746
+ add(TiledeskChatbotConst.REQ_LAST_USER_DOCUMENT_URL, m.src); // deprecated
747
+ add(TiledeskChatbotConst.REQ_LAST_USER_DOCUMENT_AS_ATTACHMENT_URL, m.src);
748
+
749
+ const inlineUrl = m.src.replace("/download", "/");
750
+ add(TiledeskChatbotConst.REQ_LAST_USER_DOCUMENT_AS_INLINE_URL, inlineUrl);
751
+
752
+ add(TiledeskChatbotConst.REQ_LAST_USER_DOCUMENT_NAME, m.name);
753
+ add(TiledeskChatbotConst.REQ_LAST_USER_DOCUMENT_TYPE, m.type);
751
754
  }
752
755
  }
753
756
 
757
+ // --- LEAD ---
754
758
  if (message && message.request && message.request.lead) {
755
759
  winston.debug("(TiledeskChatbotUtil) Lead found with email: " + message.request.lead.email + " and lead.fullname " + message.request.lead.fullname);
756
- let currentLeadEmail = await chatbot.getParameter(TiledeskChatbotConst.REQ_LEAD_EMAIL_KEY);
757
- winston.debug("(TiledeskChatbotUtil) You lead email from attributes: " + currentLeadEmail);
758
- if (message.request.lead.email && !currentLeadEmail) {
759
- // worth saving
760
- winston.debug("(TiledeskChatbotUtil) worth saving email");
761
- try {
762
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LEAD_EMAIL_KEY, message.request.lead.email);
763
- }
764
- catch(error) {
765
- winston.error("(TiledeskChatbotUtil) Error on setting userEmail:", error);
766
- }
767
- }
768
- let currentLeadName = await chatbot.getParameter(TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY);
769
- winston.debug("(TiledeskChatbotUtil) You lead email from attributes: " + currentLeadEmail);
770
- if (message.request.lead.fullname && !currentLeadName) {
771
- // worth saving
772
- winston.debug("(TiledeskChatbotUtil) worth saving email");
773
- try {
774
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY, message.request.lead.fullname);
775
- }
776
- catch(error) {
777
- winston.error("(TiledeskChatbotUtil) Error on setting userFullname: ", error);
778
- }
779
- }
760
+ const lead = message.request.lead;
761
+
762
+ const savedEmail = await chatbot.getParameter(TiledeskChatbotConst.REQ_LEAD_EMAIL_KEY);
763
+ if (lead.email && !savedEmail) add(TiledeskChatbotConst.REQ_LEAD_EMAIL_KEY, lead.email);
764
+
765
+ const savedName = await chatbot.getParameter(TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY);
766
+ if (lead.fullname && !savedName) add(TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY, lead.fullname);
780
767
 
781
768
  if (message.request.lead.phone) {
782
- await chatbot.addParameter(TiledeskChatbotConst.REQ_USER_PHONE_KEY, message.request.lead.phone);
769
+ add(TiledeskChatbotConst.REQ_USER_PHONE_KEY, lead.phone);
783
770
  }
784
- if (message.request.lead.lead_id && (message.request.lead.lead_id.startsWith("wab-") ||
785
- message.request.lead.lead_id.startsWith("vxml-") ||
786
- message.request.lead.lead_id.startsWith(CHANNEL_NAME.VOICE_TWILIO) ||
787
- message.request.lead.lead_id.startsWith(CHANNEL_NAME.SMS))) {
788
- const splits = message.request.lead.lead_id.split("-");
789
- if (splits && splits.length > 1) {
790
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CURRENT_PHONE_NUMBER_KEY,splits[1]);
771
+ if (lead.lead_id) {
772
+ const prefixes = ["wab-", "vxml-", CHANNEL_NAME.VOICE_TWILIO, CHANNEL_NAME.SMS];
773
+ if (prefixes.some(pref => lead.lead_id.startsWith(pref))) {
774
+ const parts = lead.lead_id.split("-");
775
+ if (parts[1]) add(TiledeskChatbotConst.REQ_CURRENT_PHONE_NUMBER_KEY, parts[1]);
791
776
  }
792
777
  }
793
778
  if (message.request.lead._id) {
794
- await chatbot.addParameter(TiledeskChatbotConst.REQ_USER_LEAD_ID_KEY, message.request.lead._id);
779
+ add(TiledeskChatbotConst.REQ_USER_LEAD_ID_KEY, lead._id);
795
780
  }
796
781
  if (message.request.lead.company) {
797
- await chatbot.addParameter(TiledeskChatbotConst.REQ_USER_COMPANY_KEY, message.request.lead.company);
782
+ add(TiledeskChatbotConst.REQ_USER_COMPANY_KEY, lead.company);
798
783
  }
799
784
  if (message.request.ticket_id) {
800
- await chatbot.addParameter(TiledeskChatbotConst.REQ_TICKET_ID_KEY, message.request.ticket_id);
785
+ add(TiledeskChatbotConst.REQ_TICKET_ID_KEY, message.request.ticket_id);
801
786
  }
802
787
  }
803
788
 
804
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_MESSAGE_ID_KEY, messageId);
789
+ // --- LAST MESSAGE ID ---
790
+ const messageId = message._id;
791
+ add(TiledeskChatbotConst.REQ_LAST_MESSAGE_ID_KEY, messageId);
792
+
793
+ // --- LOCATION ---
805
794
  if (message.request && message.request.location && message.request.location.country) {
806
- await chatbot.addParameter(TiledeskChatbotConst.REQ_COUNTRY_KEY, message.request.location.country);
795
+ add(TiledeskChatbotConst.REQ_COUNTRY_KEY, message.request.location.country);
807
796
  }
808
797
  if (message.request && message.request.location && message.request.location.city) {
809
- await chatbot.addParameter(TiledeskChatbotConst.REQ_CITY_KEY, message.request.location.city);
798
+ add(TiledeskChatbotConst.REQ_CITY_KEY, message.request.location.city);
810
799
  }
800
+
801
+ // --- USER CONTEXT ---
811
802
  if (message.request) {
812
- let user_language = message.request["language"];
813
- if (message.request["language"]) {
814
- var languages = parser.parse(message.request["language"]);
815
- if (languages && languages.length > 0 && languages[0].code) {
816
- user_language = languages[0].code;
817
- }
803
+ let userLang = message.request.language;
804
+ if (userLang) {
805
+ const parsed = parser.parse(userLang);
806
+ if (parsed?.[0]?.code) userLang = parsed[0].code;
818
807
  }
819
- await chatbot.addParameter(TiledeskChatbotConst.REQ_USER_SOURCE_PAGE_KEY, message.request.sourcePage);
820
- await chatbot.addParameter(TiledeskChatbotConst.REQ_USER_LANGUAGE_KEY, user_language);
821
- await chatbot.addParameter(TiledeskChatbotConst.REQ_USER_AGENT_KEY, message.request.userAgent);
808
+
809
+ add(TiledeskChatbotConst.REQ_USER_SOURCE_PAGE_KEY, message.request.sourcePage);
810
+ add(TiledeskChatbotConst.REQ_USER_LANGUAGE_KEY, userLang);
811
+ add(TiledeskChatbotConst.REQ_USER_AGENT_KEY, message.request.userAgent);
812
+
822
813
  if (message.request.attributes && message.request.attributes.decoded_jwt) {
823
- await chatbot.addParameter(TiledeskChatbotConst.REQ_DECODED_JWT_KEY, message.request.attributes.decoded_jwt);
814
+ add(TiledeskChatbotConst.REQ_DECODED_JWT_KEY, message.request.attributes.decoded_jwt);
824
815
  }
825
- if (message.request.requester) {
826
- if (message.request.requester.isAuthenticated === true) {
827
- await chatbot.addParameter(TiledeskChatbotConst.REQ_REQUESTER_IS_AUTHENTICATED_KEY, true);
828
- }
829
- else {
830
- await chatbot.addParameter(TiledeskChatbotConst.REQ_REQUESTER_IS_AUTHENTICATED_KEY, false);
831
- }
832
- }
833
- }
834
- if (message.request && message.request.department) {
835
- // It was an error when getting this from widget message's attributes
836
- // await chatbot.addParameter(TiledeskChatbotConst.REQ_DEPARTMENT_ID_KEY, message.attributes.departmentId);
837
- // await chatbot.addParameter(TiledeskChatbotConst.REQ_DEPARTMENT_NAME_KEY, message.attributes.departmentName);
838
- // get from request.department instead
839
- await chatbot.addParameter(TiledeskChatbotConst.REQ_DEPARTMENT_ID_KEY, message.request.department._id);
840
- await chatbot.addParameter(TiledeskChatbotConst.REQ_DEPARTMENT_NAME_KEY, message.request.department.name);
816
+
817
+ const auth = !!message.request.requester?.isAuthenticated;
818
+ add(TiledeskChatbotConst.REQ_REQUESTER_IS_AUTHENTICATED_KEY, auth);
841
819
  }
842
- else if (message.attributes && message.attributes.departmentId) {
843
- await chatbot.addParameter(TiledeskChatbotConst.REQ_DEPARTMENT_ID_KEY, message.attributes.departmentId);
844
- await chatbot.addParameter(TiledeskChatbotConst.REQ_DEPARTMENT_NAME_KEY, message.attributes.departmentName);
820
+
821
+ // --- DEPARTMENT ---
822
+ const dep = message.request?.department || message.attributes;
823
+ if (dep) {
824
+ add(TiledeskChatbotConst.REQ_DEPARTMENT_ID_KEY, dep.departmentId || dep._id);
825
+ add(TiledeskChatbotConst.REQ_DEPARTMENT_NAME_KEY, dep.departmentName || dep.name);
845
826
  }
846
827
 
828
+ // --- EMAIL ATTRIBUTES ---
847
829
  if (message.attributes) {
848
- const attrFields = [
849
- { key: TiledeskChatbotConst.REQ_EMAIL_SUBJECT, attr: "email_subject" },
850
- { key: TiledeskChatbotConst.REQ_EMAIL_TO, attr: "email_toEmail" },
851
- { key: TiledeskChatbotConst.REQ_EMAIL_FROM, attr: "email_fromEmail" },
852
- { key: TiledeskChatbotConst.REQ_EMAIL_MESSAGE_ID, attr: "email_messageId" },
853
- { key: TiledeskChatbotConst.REQ_EMAIL_REPLY_TO, attr: "email_replyTo" },
854
- { key: TiledeskChatbotConst.REQ_EMAIL_EML, attr: "email_eml" },
855
- { key: TiledeskChatbotConst.REQ_EMAIL_ATTACHMENTS_LINK, attr: "link" },
856
- { key: TiledeskChatbotConst.REQ_EMAIL_ATTACHMENTS_FILES, attr: "attachments" },
857
- // aggiungi qui altri campi se necessario
830
+ const emailMapping = [
831
+ ["email_subject", TiledeskChatbotConst.REQ_EMAIL_SUBJECT],
832
+ ["email_toEmail", TiledeskChatbotConst.REQ_EMAIL_TO],
833
+ ["email_fromEmail", TiledeskChatbotConst.REQ_EMAIL_FROM],
834
+ ["email_messageId", TiledeskChatbotConst.REQ_EMAIL_MESSAGE_ID],
835
+ ["email_replyTo", TiledeskChatbotConst.REQ_EMAIL_REPLY_TO],
836
+ ["email_eml", TiledeskChatbotConst.REQ_EMAIL_EML],
837
+ ["link", TiledeskChatbotConst.REQ_EMAIL_ATTACHMENTS_LINK],
838
+ ["attachments", TiledeskChatbotConst.REQ_EMAIL_ATTACHMENTS_FILES]
858
839
  ];
859
- for (const field of attrFields) {
860
- if (message.attributes[field.attr] !== undefined && message.attributes[field.attr] !== null) {
861
- await chatbot.addParameter(field.key, message.attributes[field.attr]);
840
+
841
+ for (const [attr, key] of emailMapping) {
842
+ if (message.attributes[attr] !== undefined) {
843
+ add(key, message.attributes[attr]);
862
844
  }
863
845
  }
864
846
  }
865
847
 
848
+ // --- PAYLOAD ---
866
849
  if (message && message.request && message.request.attributes && message.request.attributes.payload) {
867
850
  if (!message.attributes) {
868
851
  message.attributes = {}
@@ -873,15 +856,15 @@ class TiledeskChatbotUtil {
873
856
  if (message.attributes) {
874
857
  winston.debug("(TiledeskChatbotUtil) Ok message.attributes ", message.attributes);
875
858
 
876
- await chatbot.addParameter(TiledeskChatbotConst.REQ_END_USER_ID_KEY, message.attributes.requester_id);
877
- await chatbot.addParameter(TiledeskChatbotConst.REQ_END_USER_IP_ADDRESS_KEY, message.attributes.ipAddress);
859
+ add(TiledeskChatbotConst.REQ_END_USER_ID_KEY, message.attributes.requester_id);
860
+ add(TiledeskChatbotConst.REQ_END_USER_IP_ADDRESS_KEY, message.attributes.ipAddress);
878
861
  if (message.attributes.payload) {
879
862
  try {
880
863
  for (const [key, value] of Object.entries(message.attributes.payload)) {
881
864
  const value_type = typeof value;
882
- await chatbot.addParameter(key, value);
865
+ add(key, value);
883
866
  }
884
- await chatbot.addParameter("payload", message.attributes.payload);
867
+ add("payload", message.attributes.payload);
885
868
  }
886
869
  catch(err) {
887
870
  winston.error("(TiledeskChatbotUtil) Error importing message payload in request variables: ", err);
@@ -891,19 +874,19 @@ class TiledeskChatbotUtil {
891
874
  // TODO - REMOVE - THEY ARE IN ATTRIBUTES.PAYLOAD
892
875
  // voice-vxml attributes
893
876
  if (message.attributes.dnis) {
894
- await chatbot.addParameter("dnis", message.attributes.dnis);
877
+ add("dnis", message.attributes.dnis);
895
878
  }
896
879
  if (message.attributes.callId) {
897
- await chatbot.addParameter("callId", message.attributes.callId);
880
+ add("callId", message.attributes.callId);
898
881
  }
899
882
  if (message.attributes.ani) {
900
- await chatbot.addParameter("ani", message.attributes.ani);
883
+ add("ani", message.attributes.ani);
901
884
  }
902
885
  }
903
886
 
904
887
 
905
888
 
906
-
889
+ // --- GLOBALS ---
907
890
  const _bot = chatbot.bot; // aka FaqKB
908
891
  winston.debug("(TiledeskChatbotUtil) Adding Globals to context: ", _bot);
909
892
 
@@ -911,7 +894,7 @@ class TiledeskChatbotUtil {
911
894
  winston.debug("(TiledeskChatbotUtil) Got Globals: ", _bot.attributes.globals);
912
895
  _bot.attributes.globals.forEach(async (global_var) => {
913
896
  winston.error("(TiledeskChatbotUtil) Adding global: " + global_var.key + " value: " + global_var.value);
914
- await chatbot.addParameter(global_var.key, global_var.value);
897
+ add(global_var.key, global_var.value);
915
898
  });
916
899
  }
917
900
  // await chatbot.addParameter("testVar",
@@ -922,6 +905,13 @@ class TiledeskChatbotUtil {
922
905
  // }
923
906
  // }
924
907
  // );
908
+
909
+
910
+ // --- FINAL BATCH EXECUTION ---
911
+ await Promise.all([
912
+ ...addQueue.map(([key, value]) => chatbot.addParameter(key, value)),
913
+ ...deleteQueue.map(key => chatbot.deleteParameter(key))
914
+ ]);
925
915
 
926
916
  } catch(error) {
927
917
  winston.error("(TiledeskChatbotUtil) updateRequestAttributes Error: ", error);
@@ -951,28 +941,14 @@ class TiledeskChatbotUtil {
951
941
  }
952
942
 
953
943
  static validateRequestId(requestId, projectId) {
954
- let isValid = false;
955
- if (requestId.startsWith("support-group-")) {
956
- const parts = requestId.split("-");
957
- if (parts.length >= 4) {
958
- isValid = (parts[0] === "support" && parts[1] === "group" && parts[2] === projectId && parts[3].length > 0);
959
- }
960
- else {
961
- isValid = false;
962
- }
963
- } else if (requestId.startsWith("automation-request-")) {
964
- const parts = requestId.split("-");
965
- if (parts.length === 4 || parts.length === 5) {
966
- isValid = (parts[0] === "automation" && parts[1] === "request" && parts[2] === projectId && parts[3].length > 0);
967
- }
968
- else {
969
- isValid = false;
970
- }
971
- }
972
- else {
973
- isValid = false;
974
- }
975
- return isValid;
944
+ if (!requestId || !projectId) return false;
945
+
946
+ // Pattern for support-group-{projectId}-{id}
947
+ const supportPattern = new RegExp(`^support-group-${projectId}-\\S+$`);
948
+ // Pattern for automation-request-{projectId}-{id} or automation-request-{projectId}-{id}-something
949
+ const automationPattern = new RegExp(`^automation-request-${projectId}-\\S+(-\\S+)?$`);
950
+
951
+ return supportPattern.test(requestId) || automationPattern.test(requestId);
976
952
  }
977
953
 
978
954
  static userFlowAttributes(flowAttributes) {