@tiledesk/tiledesk-tybot-connector 0.2.85 → 0.2.88

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,18 @@
5
5
  available on:
6
6
  ▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
7
7
 
8
+ # v0.2.88
9
+ - Added DirContactUpdate (aka LeadUpdate). No test case added for LeadUpdate. Only testable with a validation test.
10
+ - Fixed: Attribute parameters userFullname & userEmail now are able to "bypass" the request.lead not correctly updating on the same conversation. If updated in the flow (through LeadUpdate action), they will maintain their own value through the current conversation flow.
11
+
12
+ # v0.2.87
13
+ - Fixed DirAssistant empty error {}
14
+ - Added to DirAssistant "lastMessageData" attribute (The message content original JSON structure useful to get annotations in messages, message type etc.)
15
+
16
+ # v0.2.86
17
+ - Added to ifOnlineAgents Action: ignoreProjectWideOperatingHours = action.ignoreOperatingHours;
18
+ - Updated ifOnlineAgents with get available agents with 'raw' option
19
+
8
20
  # v0.2.85
9
21
  - Improved "If operating hours" action with time slots
10
22
  - Other fix (?)
@@ -78,7 +78,7 @@ class MockBotsDataSource {
78
78
  async getByIntentDisplayNameCache(botId, key, tdcache) {
79
79
  let faq = null;
80
80
  if (tdcache) {
81
- // console.log("mock chache. anyway in mock getting faq from datasource...");
81
+ // console.log("mock cache. anyway in mock getting faq from datasource...");
82
82
  faq = await this.getByIntentDisplayName(botId, key);
83
83
  // console.log("faq found in datasource.:", JSON.stringify(faq));
84
84
  }
@@ -436,6 +436,9 @@ class TiledeskChatbotUtil {
436
436
  if (fullName.trim() === chatbot_name) {
437
437
  fullName = "bot:" + fullName;
438
438
  }
439
+ else {
440
+ fullName = "user:" + fullName;
441
+ }
439
442
  return "<" + fullName + ">";
440
443
  }
441
444
  }
@@ -594,23 +597,36 @@ class TiledeskChatbotUtil {
594
597
  // await chatbot.addParameter("lastUserDocumentType", null);
595
598
  // }
596
599
  if (message && message.request && message.request.lead) {
597
- console.log("lead found. lead.email:", message.request.lead.email, "lead.fullname:", message.request.lead.fullname)
598
- if (message.request.lead.email) {
599
- await chatbot.addParameter(TiledeskChatbotConst.REQ_LEAD_EMAIL_KEY, message.request.lead.email);
600
+ if (chatbot.log) {console.log("lead found. lead.email:", message.request.lead.email, "lead.fullname:", message.request.lead.fullname)}
601
+ let currentLeadEmail = await chatbot.getParameter(TiledeskChatbotConst.REQ_LEAD_EMAIL_KEY);
602
+ if (chatbot.log) {console.log("You lead email from attributes:", currentLeadEmail, "message.request.lead.email:", message.request.lead.email);}
603
+ if (message.request.lead.email && !currentLeadEmail) {
604
+ // worth saving
605
+ if (chatbot.log) {console.log("worth saving email. lead found. lead.email:", message.request.lead.email, "lead.fullname:", message.request.lead.fullname)}
606
+ try {
607
+ await chatbot.addParameter(TiledeskChatbotConst.REQ_LEAD_EMAIL_KEY, message.request.lead.email);
608
+ }
609
+ catch(error) {
610
+ console.error("Error on setting userEmail:", error);
611
+ }
600
612
  }
601
- // if (message.request.lead.fullname && !message.request.lead.fullname.startsWith("guest#")) {
602
- if (message.request.lead.fullname) {
613
+ let currentLeadName = await chatbot.getParameter(TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY);
614
+ if (chatbot.log) {console.log("You lead name from attributes:", currentLeadName, "message.request.lead.fullname:", message.request.lead.fullname)}
615
+ // if (message.request.lead.fullname && message.request.lead.fullname.startsWith("guest#") && !currentLeadName) {
616
+ // if (message.request.lead.fullname) {
617
+ if (message.request.lead.fullname && !currentLeadName) {
603
618
  // worth saving
604
- console.log("worth saving. lead found. lead.email:", message.request.lead.email, "lead.fullname:", message.request.lead.fullname)
619
+ if (chatbot.log) {console.log("worth saving fullname. lead found. lead.email:", message.request.lead.email, "lead.fullname:", message.request.lead.fullname)}
605
620
  try {
606
621
  await chatbot.addParameter(TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY, message.request.lead.fullname);
607
622
  }
608
623
  catch(error) {
609
624
  console.error("Error on setting userFullname:", error);
610
625
  }
611
- }
612
- else {
613
- // console.log("!lead.fullname");
626
+ // }
627
+ // else {
628
+ // // console.log("!lead.fullname");
629
+ // }
614
630
  }
615
631
  // console.log("Getting userPhone:", JSON.stringify(message.request));
616
632
  if (message.request.lead.phone) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-tybot-connector",
3
- "version": "0.2.85",
3
+ "version": "0.2.88",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -170,6 +170,7 @@ class DirAssistant {
170
170
  // process.exit(0);
171
171
  if (lastMessage !== null) {
172
172
  await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, assignResultTo, lastMessage);
173
+ await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, "lastMessageData", messages.data[0].content); // content is an array, see on this source end for messages structure example, including content. Ex get annotation[0]: content[0].text.annotations[0]
173
174
  if (trueIntent) {
174
175
  await this.#executeCondition(true, trueIntent, null, falseIntent, null);
175
176
  callback(true);
@@ -624,11 +625,11 @@ class DirAssistant {
624
625
  data = err.response.data;
625
626
  }
626
627
  callback(
627
- null, {
628
+ {
628
629
  status: status,
629
630
  data: data,
630
631
  error: errorMessage
631
- }
632
+ }, data
632
633
  );
633
634
  }
634
635
  });
@@ -642,4 +643,88 @@ class DirAssistant {
642
643
 
643
644
 
644
645
 
645
- module.exports = { DirAssistant };
646
+ module.exports = { DirAssistant };
647
+
648
+ // Messages list response example
649
+
650
+ /*
651
+ {
652
+ "object": "list",
653
+ "data": [
654
+ {
655
+ "id": "msg_FfKaNU82uBYQU9gANFkKJ5Wi",
656
+ "object": "thread.message",
657
+ "created_at": 1721681044,
658
+ "assistant_id": null,
659
+ "thread_id": "thread_fN0rAdyJlPmN9uteMP0yWsCl",
660
+ "run_id": null,
661
+ "role": "user",
662
+ "content": [
663
+ {
664
+ "type": "text",
665
+ "text": {
666
+ "value": "vendete sedie di altezza superiore o uguale a 50 cm?",
667
+ "annotations": []
668
+ }
669
+ }
670
+ ],
671
+ "file_ids": [],
672
+ "metadata": {}
673
+ },
674
+ {
675
+ "id": "msg_Ddxnqi7M9vvLdS9YYO4FHjVt",
676
+ "object": "thread.message",
677
+ "created_at": 1721680934,
678
+ "assistant_id": "asst_qNjiwCVxo3kL2mnN1QyP50Zb",
679
+ "thread_id": "thread_fN0rAdyJlPmN9uteMP0yWsCl",
680
+ "run_id": "run_k8mPIrZPnsO0hAiezD9y2f1t",
681
+ "role": "assistant",
682
+ "content": [
683
+ {
684
+ "type": "text",
685
+ "text": {
686
+ "value": "Una delle best practices raccomandate per garantire un alto livello di sicurezza informatica per la linea di prodotti \"boss\" è la seguente:\n\n- Aggiornare i dispositivi con l'ultima versione del firmware disponibile. È possibile consultare il portale KSA per verificare la disponibilità degli aggiornamenti【6:0†source】.\n\nSe hai altri dubbi o necessiti di ulteriori informazioni, non esitare a chiedere!",
687
+ "annotations": [
688
+ {
689
+ "type": "file_citation",
690
+ "text": "【6:0†source】",
691
+ "start_index": 305,
692
+ "end_index": 317,
693
+ "file_citation": {
694
+ "file_id": "file-dwR6qSwVUIrhImd9espzExGw",
695
+ "quote": ""
696
+ }
697
+ }
698
+ ]
699
+ }
700
+ }
701
+ ],
702
+ "file_ids": [],
703
+ "metadata": {}
704
+ },
705
+ {
706
+ "id": "msg_ng244T4mymroFWZ912r9DvWZ",
707
+ "object": "thread.message",
708
+ "created_at": 1721680931,
709
+ "assistant_id": null,
710
+ "thread_id": "thread_fN0rAdyJlPmN9uteMP0yWsCl",
711
+ "run_id": null,
712
+ "role": "user",
713
+ "content": [
714
+ {
715
+ "type": "text",
716
+ "text": {
717
+ "value": "dimmi una delle best practices che conosci",
718
+ "annotations": []
719
+ }
720
+ }
721
+ ],
722
+ "file_ids": [],
723
+ "metadata": {}
724
+ }
725
+ ],
726
+ "first_id": "msg_FfKaNU82uBYQU9gANFkKJ5Wi",
727
+ "last_id": "msg_ng244T4mymroFWZ912r9DvWZ",
728
+ "has_more": false
729
+ }
730
+ */
@@ -54,8 +54,21 @@ class DirContactUpdate {
54
54
  const filler = new Filler();
55
55
  let updateProperties = {}
56
56
  for (const [key, value] of Object.entries(contactProperties)) {
57
- updateProperties[key] = filler.fill(value, requestAttributes);
58
- if (this.log) {console.log("(DirContactUpdate) updating property:", key, "value:", value); }
57
+ let filled_value = filler.fill(value, requestAttributes);
58
+ if (this.log) {console.log("(DirContactUpdate) setting property key:",key, "with value:", value, "filled value:", filled_value); }
59
+ updateProperties[key] = filled_value;
60
+ if (key === "fullname") {
61
+ await this.context.chatbot.addParameter(TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY, filled_value);
62
+ if (this.log) {console.log("(DirContactUpdate) updating attribute:",TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY, "with property key:", key, "and value:", filled_value); }
63
+ }
64
+ else if ( key === "email") {
65
+ await this.context.chatbot.addParameter(TiledeskChatbotConst.REQ_LEAD_EMAIL_KEY, filled_value);
66
+ if (this.log) {console.log("(DirContactUpdate) updating attribute:",TiledeskChatbotConst.REQ_LEAD_EMAIL_KEY, "with property key:", key, "and value:", filled_value); }
67
+ }
68
+ // else if (key === "phone") {
69
+ // static REQ_USER_PHONE_KEY = "userPhone";
70
+ // }
71
+ if (this.log) {console.log("(DirContactUpdate) updating property:", key, "value:", filled_value); }
59
72
  }
60
73
  const leadId = requestAttributes[TiledeskChatbotConst.REQ_USER_LEAD_ID_KEY];
61
74
  this.tdclient.updateLead(leadId, updateProperties, null, null, () => {
@@ -63,33 +76,34 @@ class DirContactUpdate {
63
76
  // send hidden info to update widget lead fullname only if it is a conversation!
64
77
  if (this.log) {console.log("(DirContactUpdate) requestId:", this.requestId); }
65
78
  if (this.log) {console.log("(DirContactUpdate) updateProperties:", updateProperties); }
66
- if (this.log) {console.log("(DirContactUpdate) updateProperties['userFullname']:", updateProperties['userFullname']); }
67
- if (this.requestId.startsWith("support-group") && updateProperties['userFullname']) {
68
- if (this.log) {console.log("(DirContactUpdate) send hidden info to update widget lead fullname"); }
69
- const userFullname = updateProperties['userFullname'];
70
- const updateLeadDataOnWidgetMessage = {
71
- type: "text",
72
- text: "Updated lead fullname on widget with: " + userFullname,
73
- attributes: {
74
- // subtype: "info",
75
- updateUserFullname: userFullname
76
- }
77
- };
78
- if (this.log) {console.log("(DirContactUpdate) sending updateLeadDataOnWidgetMessage:", updateLeadDataOnWidgetMessage); }
79
- this.context.tdclient.sendSupportMessage(
80
- this.requestId,
81
- updateLeadDataOnWidgetMessage,
82
- (err) => {
83
- if (err) {
84
- console.error("(DirContactUpdate) Error sending reply:", err);
85
- }
86
- if (this.log) {console.log("(DirContactUpdate) hidden message sent:", updateLeadDataOnWidgetMessage);}
87
- callback();
88
- });
89
- }
90
- else {
91
- callback();
92
- }
79
+ if (this.log) {console.log("(DirContactUpdate) updateProperties['fullname']:", updateProperties['fullname']); }
80
+ callback();
81
+ // if (this.requestId.startsWith("support-group") && updateProperties['userFullname']) {
82
+ // if (this.log) {console.log("(DirContactUpdate) send hidden info to update widget lead fullname"); }
83
+ // const userFullname = updateProperties['fullname'];
84
+ // const updateLeadDataOnWidgetMessage = {
85
+ // type: "text",
86
+ // text: "Updated lead fullname on widget with: " + userFullname,
87
+ // attributes: {
88
+ // // subtype: "info",
89
+ // updateUserFullname: userFullname
90
+ // }
91
+ // };
92
+ // if (this.log) {console.log("(DirContactUpdate) sending updateLeadDataOnWidgetMessage:", updateLeadDataOnWidgetMessage); }
93
+ // this.context.tdclient.sendSupportMessage(
94
+ // this.requestId,
95
+ // updateLeadDataOnWidgetMessage,
96
+ // (err) => {
97
+ // if (err) {
98
+ // console.error("(DirContactUpdate) Error sending reply:", err);
99
+ // }
100
+ // if (this.log) {console.log("(DirContactUpdate) hidden message sent:", updateLeadDataOnWidgetMessage);}
101
+ // callback();
102
+ // });
103
+ // }
104
+ // else {
105
+ // callback();
106
+ // }
93
107
  });
94
108
  }
95
109
  }
@@ -52,8 +52,24 @@ class DirIfOnlineAgentsV2 {
52
52
  let stopOnConditionMet = true; //action.stopOnConditionMet;
53
53
 
54
54
  try {
55
- const result = await this.openNow();
56
- if (result && result.isopen) {
55
+ const ignoreProjectWideOperatingHours = action.ignoreOperatingHours;
56
+ let isOpen = false;
57
+ if (ignoreProjectWideOperatingHours === true) {
58
+ // always go on to only check agents availability
59
+ isOpen = true;
60
+ }
61
+ else {
62
+ const result = await this.openNow();
63
+ if (result && result.isopen) {
64
+ isOpen = true;
65
+ }
66
+ else {
67
+ isOpen = false;
68
+ }
69
+ }
70
+
71
+ // if (result && result.isopen) {
72
+ if (isOpen === true) { // always true if ignoreProjectWideOperatingHours = true
57
73
  const selectedOption = action.selectedOption;
58
74
 
59
75
  let agents;
@@ -102,11 +118,10 @@ class DirIfOnlineAgentsV2 {
102
118
  }
103
119
  else { // if (checkAll) => go project-wide
104
120
  if (this.log) {console.log("(DirIfOnlineAgents) selectedOption === all"); }
105
- agents = await this.getProjectAvailableAgents();
121
+ agents = await this.getProjectAvailableAgents(true);
106
122
  if (this.log) {console.log("(DirIfOnlineAgents) agents:", agents); }
107
123
  }
108
124
 
109
- console.log("anyway qui...");
110
125
  if (agents && agents.length > 0) {
111
126
  if (trueIntent) {
112
127
  let intentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
@@ -134,6 +149,18 @@ class DirIfOnlineAgentsV2 {
134
149
  this.chatbot.addParameter("flowError", "(If online Agents) No path for 'no available agents' defined.");
135
150
  callback();
136
151
  }
152
+ } else {
153
+ if (falseIntent) {
154
+ let intentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
155
+ if (this.log) {console.log("!agents (!openHours) => falseIntent");}
156
+ console.log("!agents (!openHours) => falseIntent BECAUSE CLOSED"); //PROD
157
+ this.intentDir.execute(intentDirective, () => {
158
+ callback();
159
+ });
160
+ }
161
+ else {
162
+ callback();
163
+ }
137
164
  }
138
165
  }
139
166
  catch(err) {
@@ -157,19 +184,51 @@ class DirIfOnlineAgentsV2 {
157
184
  });
158
185
  }
159
186
 
160
- async getProjectAvailableAgents() {
187
+ async getProjectAvailableAgents(raw, callback) {
161
188
  return new Promise( (resolve, reject) => {
162
- this.tdclient.getProjectAvailableAgents((err, agents) => {
163
- if (err) {
164
- reject(err);
165
- }
166
- else {
167
- resolve(agents);
168
- }
169
- });
170
- })
189
+ const URL = `${this.context.TILEDESK_APIURL}/projects/${this.context.projectId}/users/availables?raw=${raw}`
190
+ const HTTPREQUEST = {
191
+ url: URL,
192
+ headers: {
193
+ 'Content-Type' : 'application/json',
194
+ 'Authorization': this.fixToken(this.context.token)
195
+ },
196
+ // json: true,
197
+ method: 'GET',
198
+ };
199
+ this.#myrequest(
200
+ HTTPREQUEST,
201
+ function(err, resbody) {
202
+ if (err) {
203
+ if (callback) {
204
+ callback(err);
205
+ }
206
+ reject(err);
207
+ }
208
+ else {
209
+ if (callback) {
210
+ callback(null, resbody);
211
+ }
212
+ resolve(resbody);
213
+ }
214
+ }, this.log);
215
+ });
216
+
171
217
  }
172
218
 
219
+ // async getProjectAvailableAgents() {
220
+ // return new Promise( (resolve, reject) => {
221
+ // this.tdclient.getProjectAvailableAgents((err, agents) => {
222
+ // if (err) {
223
+ // reject(err);
224
+ // }
225
+ // else {
226
+ // resolve(agents);
227
+ // }
228
+ // });
229
+ // })
230
+ // }
231
+
173
232
  async getDepartmentAvailableAgents(depId) {
174
233
  return new Promise( (resolve, reject) => {
175
234
  this.tdclient.getDepartment(depId, async (error, dep) => {
@@ -237,7 +296,7 @@ class DirIfOnlineAgentsV2 {
237
296
  }
238
297
  else {
239
298
  // no group => assigned to all teammates
240
- const agents = await this.getProjectAvailableAgents();
299
+ const agents = await this.getProjectAvailableAgents(true);
241
300
  resolve(agents);
242
301
  }
243
302
  }
@@ -1,6 +1,7 @@
1
1
  // const { TiledeskClient } = require('@tiledesk/tiledesk-client');
2
2
  let axios = require('axios');
3
3
  const { DirIntent } = require('./DirIntent');
4
+ let https = require("https");
4
5
  const ms = require('minimist-string');
5
6
 
6
7
  class DirIfOpenHours {
@@ -91,8 +92,8 @@ class DirIfOpenHours {
91
92
  }
92
93
 
93
94
  let slot_id = null;
94
- if (action.slot_id) {
95
- slot_id = action.slot_id;
95
+ if (action.slotId) {
96
+ slot_id = action.slotId;
96
97
  }
97
98
 
98
99
  const server_base_url = process.env.API_ENDPOINT || process.env.API_URL;
@@ -78,12 +78,12 @@ class DirRandomReply {
78
78
  message.attributes = {}
79
79
  }
80
80
  // Reserved names: userEmail, userFullname
81
- if (requestVariables['userEmail']) {
82
- message.attributes.updateUserEmail = requestVariables['userEmail'];
83
- }
84
- if (requestVariables['userFullname']) {
85
- message.attributes.updateUserFullname = requestVariables['userFullname'];
86
- }
81
+ // if (requestVariables['userEmail']) {
82
+ // message.attributes.updateUserEmail = requestVariables['userEmail'];
83
+ // }
84
+ // if (requestVariables['userFullname']) {
85
+ // message.attributes.updateUserFullname = requestVariables['userFullname'];
86
+ // }
87
87
  }
88
88
  // send!
89
89
  if (this.log) {console.log("Reply:", JSON.stringify(message))};
@@ -94,12 +94,12 @@ class DirReply {
94
94
  message.attributes = {}
95
95
  }
96
96
  // Reserved names: userEmail, userFullname
97
- if (requestAttributes['userEmail']) {
98
- message.attributes.updateUserEmail = requestAttributes['userEmail'];
99
- }
100
- if (requestAttributes['userFullname']) {
101
- message.attributes.updateUserFullname = requestAttributes['userFullname'];
102
- }
97
+ // if (requestAttributes['userEmail']) {
98
+ // message.attributes.updateUserEmail = requestAttributes['userEmail'];
99
+ // }
100
+ // if (requestAttributes['userFullname']) {
101
+ // message.attributes.updateUserFullname = requestAttributes['userFullname'];
102
+ // }
103
103
  // intent_info
104
104
  if (this.context.reply && this.context.reply.attributes && this.context.reply.attributes.intent_info) {
105
105
  message.attributes.intentName = this.context.reply.attributes.intent_info.intent_name;
@@ -234,12 +234,12 @@ class DirReplyV2 {
234
234
  message.attributes = {}
235
235
  }
236
236
  // Reserved names: userEmail, userFullname
237
- if (requestAttributes['userEmail']) {
238
- message.attributes.updateUserEmail = requestAttributes['userEmail'];
239
- }
240
- if (requestAttributes['userFullname']) {
241
- message.attributes.updateUserFullname = requestAttributes['userFullname'];
242
- }
237
+ // if (requestAttributes['userEmail']) {
238
+ // message.attributes.updateUserEmail = requestAttributes['userEmail'];
239
+ // }
240
+ // if (requestAttributes['userFullname']) {
241
+ // message.attributes.updateUserFullname = requestAttributes['userFullname'];
242
+ // }
243
243
  // intent_info
244
244
  if (this.context.reply && this.context.reply.attributes && this.context.reply.attributes.intent_info) {
245
245
  message.attributes.intentName = this.context.reply.attributes.intent_info.intent_name;