@tiledesk/tiledesk-tybot-connector 0.2.113 → 0.2.116

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
@@ -17,7 +17,21 @@ available on:
17
17
  - Added flowError on JSONCondition when result = null
18
18
  - Added fix on Filler -->
19
19
 
20
- # v0.2.113 -> test
20
+ # v0.2.116 -> test
21
+ - updates @tiledesk/tiledesk-client => v0.10.12
22
+
23
+ # v0.2.115 -> test
24
+ - removed log console.error("TiledeskExpression.evaluate() error:...")
25
+ - Log setting fix in DirectivesChatbotPlug: const tdclient = new TiledeskClient({...
26
+ - SetAttributeV2: added check for action null: if (!action) {...
27
+ - SetAttributeV2:added check with ? operator: if (action.operation?.operators === undefined && ...
28
+
29
+ # v0.2.114 -> test
30
+ - Creating draft webhook endpoint on index.js: router.post('/block/:project_id/:bot_id/:block_id' ...
31
+ - Added check on attribute size < 20Mb
32
+ - SetAttributeV2: added persistency service
33
+
34
+ # v0.2.113 -> prod
21
35
  - Fixed DirClose not importing TiledeskChatbotConst
22
36
 
23
37
  # v0.2.112 -> prod
package/TdCache.js CHANGED
@@ -28,6 +28,7 @@ class TdCache {
28
28
  // console.log('Redis Connected!');
29
29
  // });
30
30
  this.client.on('ready',function() {
31
+ console.log("connected")
31
32
  resolve();
32
33
  if (callback) {
33
34
  callback();
@@ -263,7 +263,7 @@ class TiledeskExpression {
263
263
  // console.log("res=", res)
264
264
  }
265
265
  catch (err) {
266
- console.error("(evaluateJavascriptExpression) TiledeskExpression.evaluate() error:", err.message, "- while evaluating the following expression: '" + expression + "'");
266
+ // console.error("(evaluateJavascriptExpression) TiledeskExpression.evaluate() error:", err.message, "- while evaluating the following expression: '" + expression + "'");
267
267
  }
268
268
  return res;
269
269
  }
@@ -337,7 +337,7 @@ class TiledeskExpression {
337
337
  res = vm.run(`let $data = this;${expression}`);
338
338
  }
339
339
  catch (err) {
340
- console.error("TiledeskExpression.evaluate() error:", err.message, "evaluating expression: '" + expression + "'");
340
+ // console.error("TiledeskExpression.evaluate() error:", err.message, "evaluating expression: '" + expression + "'");
341
341
  }
342
342
  return res;
343
343
  }
package/index.js CHANGED
@@ -12,6 +12,8 @@ const { MongodbBotsDataSource } = require('./models/MongodbBotsDataSource.js');
12
12
  const { MockBotsDataSource } = require('./models/MockBotsDataSource.js');
13
13
  const { TiledeskChatbotConst } = require('./models/TiledeskChatbotConst');
14
14
  const { IntentsMachineFactory } = require('./models/IntentsMachineFactory');
15
+ const { v4: uuidv4 } = require('uuid');
16
+ let axios = require('axios');
15
17
  // let parser = require('accept-language-parser');
16
18
 
17
19
  router.use(bodyParser.json({limit: '50mb'}));
@@ -208,7 +210,7 @@ router.post('/ext/:botid', async (req, res) => {
208
210
  TILEBOT_ENDPOINT:process.env.TYBOT_ENDPOINT,
209
211
  token: token,
210
212
  log: log,
211
- HELP_CENTER_API_ENDPOINT: process.env.HELP_CENTER_API_ENDPOINT,
213
+ // HELP_CENTER_API_ENDPOINT: process.env.HELP_CENTER_API_ENDPOINT,
212
214
  cache: tdcache
213
215
  }
214
216
  );
@@ -561,6 +563,41 @@ router.post('/echobot', (req, res) => {
561
563
  });
562
564
  });
563
565
 
566
+ // draft webhook
567
+ router.post('/block/:project_id/:bot_id/:block_id', async (req, res) => {
568
+ const project_id = req.params['project_id'];
569
+ const bot_id = req.params['bot_id'];
570
+ const block_id = req.params['block_id'];
571
+ const body = req.body;
572
+ console.log('/block/:project_id/:bot_id/:block_id:', project_id, "/", bot_id, "/", block_id);
573
+ console.log('/block/:project_id/:bot_id/:block_id.body', body);
574
+
575
+ // invoke block
576
+ // unique ID for each execution
577
+ const execution_id = uuidv4().replace(/-/g, '');
578
+ const request_id = "automation-request-" + project_id + "-" + execution_id;
579
+ const command = "/" + block_id;
580
+ let request = {
581
+ "payload": {
582
+ "recipient": request_id,
583
+ "text": command,
584
+ "id_project": project_id,
585
+ "request": {
586
+ "request_id": request_id
587
+ },
588
+ "attributes": {
589
+ "payload": body
590
+ }
591
+ }, token: ".."
592
+ }
593
+ console.log("sendMessageToBot()...");
594
+ sendMessageToBot(request, bot_id, async () => {
595
+ console.log("Async webhook message sent:\n", request);
596
+ res.status(200).send({"success":true});
597
+ return;
598
+ });
599
+ });
600
+
564
601
  async function startApp(settings, completionCallback) {
565
602
  console.log("Starting Tilebot...");
566
603
  //console.log("Starting Tilebot with Settings:", settings);
@@ -677,4 +714,80 @@ async function checkRequest(request_id, id_project) {
677
714
  // WARNING! Move this function in models/TiledeskChatbotUtil.js
678
715
  }
679
716
 
717
+ /**
718
+ * A stub to send message to the "ext/botId" endpoint, hosted by tilebot on:
719
+ * /${TILEBOT_ROUTE}/ext/${botId}
720
+ *
721
+ * @param {Object} message. The message to send
722
+ * @param {string} botId. Tiledesk botId
723
+ * @param {string} token. User token
724
+ */
725
+ function sendMessageToBot(message, botId, callback) {
726
+ // const jwt_token = this.fixToken(token);
727
+ const url = `${process.env.TYBOT_ENDPOINT}/ext/${botId}`;
728
+ console.log("sendMessageToBot URL", url);
729
+ const HTTPREQUEST = {
730
+ url: url,
731
+ headers: {
732
+ 'Content-Type': 'application/json'
733
+ },
734
+ json: message,
735
+ method: 'POST'
736
+ };
737
+ myrequest(
738
+ HTTPREQUEST,
739
+ function (err, resbody) {
740
+ if (err) {
741
+ if (callback) {
742
+ callback(err);
743
+ }
744
+ }
745
+ else {
746
+ if (callback) {
747
+ callback(null, resbody);
748
+ }
749
+ }
750
+ }, false
751
+ );
752
+ }
753
+
754
+ function myrequest(options, callback, log) {
755
+ if (log) {
756
+ console.log("API URL:", options.url);
757
+ console.log("** Options:", JSON.stringify(options));
758
+ }
759
+ axios(
760
+ {
761
+ url: options.url,
762
+ method: options.method,
763
+ data: options.json,
764
+ params: options.params,
765
+ headers: options.headers
766
+ })
767
+ .then((res) => {
768
+ if (log) {
769
+ console.log("Response for url:", options.url);
770
+ console.log("Response headers:\n", JSON.stringify(res.headers));
771
+ //console.log("******** Response for url:", res);
772
+ }
773
+ if (res && res.status == 200 && res.data) {
774
+ if (callback) {
775
+ callback(null, res.data);
776
+ }
777
+ }
778
+ else {
779
+ if (callback) {
780
+ callback(TiledeskClient.getErr({ message: "Response status not 200" }, options, res), null, null);
781
+ }
782
+ }
783
+ })
784
+ .catch((error) => {
785
+ console.error("An error occurred:", error);
786
+ if (callback) {
787
+ callback(error, null, null);
788
+ }
789
+ }
790
+ );
791
+ }
792
+
680
793
  module.exports = { router: router, startApp: startApp};
@@ -618,8 +618,17 @@ class TiledeskChatbot {
618
618
  }
619
619
 
620
620
  static async addParameterStatic(_tdcache, requestId, parameter_name, parameter_value) {
621
+ if (parameter_name === null || parameter_name === undefined) {
622
+ // console.error("Error saving key:", parameter_name, "value:", parameter_value);
623
+ return;
624
+ }
621
625
  const parameter_key = TiledeskChatbot.requestCacheKey(requestId) + ":parameters";
622
626
  const parameter_value_s = JSON.stringify(parameter_value);
627
+ // console.log("saving key:", parameter_name, "value:", parameter_value);
628
+ if (parameter_value_s?.length > 20000000) {
629
+ // console.log("Error. Attribute size too big (> 20mb):", parameter_value_s);
630
+ return;
631
+ }
623
632
  await _tdcache.hset(parameter_key, parameter_name, parameter_value_s);
624
633
  }
625
634
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-tybot-connector",
3
- "version": "0.2.113",
3
+ "version": "0.2.116",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -14,7 +14,7 @@
14
14
  "@tiledesk/helpcenter-query-client": "^0.1.8",
15
15
  "@tiledesk/tiledesk-chatbot-client": "^0.5.30",
16
16
  "@tiledesk/tiledesk-chatbot-util": "^0.8.39",
17
- "@tiledesk/tiledesk-client": "^0.10.5",
17
+ "@tiledesk/tiledesk-client": "^0.10.12",
18
18
  "accept-language-parser": "^1.5.0",
19
19
  "axios": "^0.27.2",
20
20
  "body-parser": "^1.19.0",
@@ -97,6 +97,11 @@ class DirSetAttributeV2 {
97
97
 
98
98
  async go(action, callback) {
99
99
  if (this.log) {console.log("(DirSetAttribute) action before filling:", JSON.stringify(action));}
100
+ if (!action) {
101
+ if (this.log) {console.log("(SetAttributeV2) Error 'action' is missing");}
102
+ callback();
103
+ return;
104
+ }
100
105
  if (action && !action.operation) {
101
106
  if (this.log) {console.log("(SetAttributeV2) Error operation is mandatory");}
102
107
  callback();
@@ -108,14 +113,16 @@ class DirSetAttributeV2 {
108
113
  if (this.log) { console.log("action.operation.operands.length", action.operation.operands.length); }
109
114
  if (this.log) { console.log("action.operation.operands[0].type", action.operation.operands[0].type); }
110
115
 
111
- // FUN FACT: THIS TOOK A LOT OF EFFERT BUT IT WAS NEVER USED. YOU CAN SIMPLY CREATE A JSON ATTRIBUTE APPLYING
116
+ // FUN FACT: THIS TOOK A LOT OF EFFORT BUT IT WAS NEVER USED. YOU CAN SIMPLY CREATE A JSON ATTRIBUTE APPLYING
112
117
  // JSONparse FUNCTION TO AN ATTRIBUTE.
118
+ // DEPRECATED because type = json is not available in the UI!
113
119
  if (action.operation.operands && action.operation.operands.length === 1 && action.operation.operands[0].type === "json") {
114
120
  if (this.log) {console.log("(SetAttributeV2) setting json value...");}
115
121
  if (this.log) { console.log("(SetAttributeV2) setting json value... destination:", action.destination); }
116
122
  const json_value = JSON.parse(action.operation.operands[0].value);
117
123
  if (this.log) { console.log("(SetAttributeV2) json_value:", json_value); }
118
- await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.destination, json_value);
124
+ await this.saveAttribute(action.destination, json_value);
125
+ // await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.destination, json_value);
119
126
  callback();
120
127
  return; // on json types no operations are permitted beyond assignment
121
128
  }
@@ -130,12 +137,12 @@ class DirSetAttributeV2 {
130
137
  // callback();
131
138
  // return;
132
139
  // }
133
- if (action.operation.operators === undefined && action.operation.operands.length !== 1) {
140
+ if (action.operation?.operators === undefined && action.operation?.operands?.length !== 1) {
134
141
  if (this.log) {console.error("(DirSetAttribute) Invalid action: operators === undefined && operands.length !== 1")};
135
142
  callback();
136
143
  return;
137
144
  }
138
- if (action.operation.operators !== undefined && action.operation.operators.length !== action.operation.operands.length - 1) {
145
+ if (action.operation?.operators !== undefined && action.operation?.operators?.length !== action.operation?.operands?.length - 1) {
139
146
  if (this.log) {console.error("(DirSetAttribute) Invalid action: operators.length !== operands.length - 1")};
140
147
  callback();
141
148
  return;
@@ -145,21 +152,89 @@ class DirSetAttributeV2 {
145
152
  // await this.fillValues(action.operation.operands);
146
153
  // }
147
154
  // console.log("dirsetattribute, action.operation.operands:", action.operation.operands);
148
- const expression = TiledeskExpression.JSONOperationToExpression(action.operation.operators, action.operation.operands);
149
- const attributes = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
150
- // console.log("dirsetattribute, attributes:", attributes);
151
- attributes.TiledeskMath = TiledeskMath;
152
- attributes.TiledeskString = TiledeskString;
153
- const result = new TiledeskExpression().evaluateJavascriptExpression(expression, attributes);
154
- // console.log("filling in setattribute, result:", result);
155
- // THE GOAL OF ATTRIBUTE-FILLING THE "DESTINATION" FIELD IS TO SUPPORT DYNAMIC ATTRIBUTES
156
- // (ATTRS WHOSE NAME IS UNKNOWN AD DESIGN-TIME)
157
- // STILL UNSUPPORTED IN UI
158
- let destination = await this.fillDestination(action.destination);
159
- await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, destination, result);
155
+ try {
156
+ const expression = TiledeskExpression.JSONOperationToExpression(action.operation?.operators, action.operation?.operands);
157
+ const attributes = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
158
+ // console.log("dirsetattribute, attributes:", attributes);
159
+ if (attributes) {
160
+ attributes.TiledeskMath = TiledeskMath;
161
+ attributes.TiledeskString = TiledeskString;
162
+ const result = new TiledeskExpression().evaluateJavascriptExpression(expression, attributes);
163
+ // console.log("filling in setattribute, result:", result);
164
+ // THE GOAL OF ATTRIBUTE-FILLING THE "DESTINATION" FIELD IS TO SUPPORT DYNAMIC ATTRIBUTES
165
+ // (ATTRS WHOSE NAME IS UNKNOWN AD DESIGN-TIME)
166
+ // STILL UNSUPPORTED IN UI
167
+ let destination = await this.fillDestination(action.destination);
168
+ await this.saveAttribute(destination, result);
169
+ }
170
+ }
171
+ catch(err) {
172
+ console.error("SetAttributeV2 error:", err);
173
+ }
174
+
175
+ // await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, destination, result);
160
176
  callback();
161
177
  }
162
178
 
179
+ async saveAttribute(key, value, persist) {
180
+ if (this.log) {
181
+ console.log("SetAttributeV2 saving attribute:", key, value, persist);
182
+ }
183
+ await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, key, value);
184
+ // if (persist) {
185
+ // console.log("SetAttributeV2 persisting...");
186
+ // await this.persistOnTiledesk(destination, result);
187
+ // }
188
+
189
+ // await make persistent autenticato con "Chatbot Token" (solo il chatbot può usare questo servizio)
190
+ // sarebbe il top che accodasse
191
+ /**
192
+ * ACL ?
193
+ * Solo agents appartenenti a quella conversazione possono accedere agli attibuti. E gli Admin
194
+ * collection flow_attributes
195
+ * {
196
+ * "projectId",
197
+ * "flowId",
198
+ * "requestId",
199
+ * attributes: [
200
+ * {"key": destination, "value": {}, 2, "Andrea"} => In pratica value è un "any"
201
+ * ]
202
+ * }
203
+ */
204
+ }
205
+
206
+ async persistOnTiledesk(key, value) {
207
+ if (!process.env.PERSIST_API_ENDPOINT) {
208
+ return;
209
+ }
210
+ const HTTPREQUEST = {
211
+ url: process.env.PERSIST_API_ENDPOINT,
212
+ headers: {
213
+ 'Content-Type': 'application/json',
214
+ 'Authorization': this.fixToken(this.context.token)
215
+ },
216
+ json: json,
217
+ method: 'POST'
218
+ }
219
+ if (this.log) { console.log("SetAttribute. HTTPREQUEST: ", HTTPREQUEST); }
220
+ this.#myrequest(
221
+ HTTPREQUEST, async (err, resbody) => {
222
+ if (err) {
223
+ if (this.log) {
224
+ console.error("SetAttribute. persistOnTiledesk() error:", err);
225
+ }
226
+ // callback();
227
+ // return;
228
+ } else {
229
+ if (this.log) { console.log("SetAttribute. Attributes saved.", JSON.stringify(resbody)); }
230
+ // callback();
231
+ // return;
232
+ }
233
+ }
234
+ );
235
+ return;
236
+ }
237
+
163
238
  async fillDestination(destination) {
164
239
  if (this.tdcache) {
165
240
  // console.log("tdcache in setattribute...", this.tdcache);
@@ -257,6 +332,62 @@ class DirSetAttributeV2 {
257
332
  console.error("Error while converting operands:", error);
258
333
  }
259
334
  }
335
+
336
+ #myrequest(options, callback) {
337
+ if (this.log) {
338
+ console.log("API URL:", options.url);
339
+ console.log("** Options:", JSON.stringify(options));
340
+ }
341
+ let axios_options = {
342
+ url: options.url,
343
+ method: options.method,
344
+ params: options.params,
345
+ headers: options.headers
346
+ }
347
+ if (options.json !== null) {
348
+ axios_options.data = options.json
349
+ }
350
+ if (this.log) {
351
+ console.log("axios_options:", JSON.stringify(axios_options));
352
+ }
353
+ if (options.url.startsWith("https:")) {
354
+ const httpsAgent = new https.Agent({
355
+ rejectUnauthorized: false,
356
+ });
357
+ axios_options.httpsAgent = httpsAgent;
358
+ }
359
+ axios(axios_options)
360
+ .then((res) => {
361
+ if (this.log) {
362
+ console.log("Response for url:", options.url);
363
+ console.log("Response headers:\n", JSON.stringify(res.headers));
364
+ }
365
+ if (res && res.status == 200 && res.data) {
366
+ if (callback) {
367
+ callback(null, res.data);
368
+ }
369
+ }
370
+ else {
371
+ if (callback) {
372
+ callback(new Error("Response status is not 200"), null);
373
+ }
374
+ }
375
+ })
376
+ .catch((error) => {
377
+ if (callback) {
378
+ callback(error, null);
379
+ }
380
+ });
381
+ }
382
+
383
+ fixToken(token) {
384
+ if (token.startsWith('JWT ')) {
385
+ return token
386
+ }
387
+ else {
388
+ return 'JWT ' + token
389
+ }
390
+ }
260
391
  }
261
392
 
262
393
  module.exports = { DirSetAttributeV2 };