@tiledesk/tiledesk-tybot-connector 0.2.27 → 0.2.29

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,14 @@
5
5
  available on:
6
6
  ▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
7
7
 
8
+ ### v0.2.29
9
+ - Added Make action
10
+
11
+ ### v0.2.28
12
+ - DirSetAttribute, added support for attribute-filling in constants
13
+ - DirSetAttribute, added function JSONparse
14
+ - Added support for Globals (aka Secrets)
15
+
8
16
  ### v0.2.27
9
17
  - Added support for removing empty text from replies: TiledeskChatbotUtil.removeEmptyReplyCommands()
10
18
  - Removed non-user-defined attributes from /ext/parameters method
@@ -209,6 +209,10 @@ class TiledeskExpression {
209
209
  "roundAsNumber": {
210
210
  name: "roundAsNumber",
211
211
  applyPattern: "TiledeskMath.round(Number(#1))"
212
+ },
213
+ "JSONparse": {
214
+ name: "JSONparse",
215
+ applyPattern: "JSON.parse(String(#1))"
212
216
  }
213
217
  }
214
218
 
@@ -230,8 +234,8 @@ class TiledeskExpression {
230
234
  }
231
235
 
232
236
  evaluateJavascriptExpression(expression, context) {
233
- // console.log("(evaluateJavascriptExpression) evaluating:", expression)
234
- // console.log("context:", context)
237
+ console.log("(evaluateJavascriptExpression) evaluating:", expression)
238
+ console.log("context:", context)
235
239
  let res = null;
236
240
  try {
237
241
  const vm = new VM({
@@ -626,9 +626,9 @@ class TiledeskChatbot {
626
626
  attributes_native_values[key] = JSON.parse(value);
627
627
  }
628
628
  }
629
- else {
630
- console.error("An error occurred. 'attributes__as_string_map' is null!");
631
- }
629
+ // else {
630
+ // console.error("Warning: 'attributes__as_string_map' is null!");
631
+ // }
632
632
  return attributes_native_values;
633
633
  }
634
634
 
@@ -518,20 +518,39 @@ class TiledeskChatbotUtil {
518
518
  }
519
519
  }
520
520
 
521
-
521
+ const _bot = chatbot.bot; // aka FaqKB
522
+ if (chatbot.log) {
523
+ console.log("Adding Globals to context..., chatbot.attributes?", JSON.stringify(_bot));
524
+ }
525
+
526
+ if (_bot.attributes && _bot.attributes.globals) {
527
+ if (chatbot.log) {console.log("Got Globals:", JSON.stringify(_bot.attributes.globals));}
528
+ _bot.attributes.globals.forEach(async (global_var) => {
529
+ if (chatbot.log) {console.log("Adding global:", global_var.key, "value:", global_var.value);}
530
+ await chatbot.addParameter(global_var.key, global_var.value);
531
+ });
532
+ }
533
+ // await chatbot.addParameter("testVar",
534
+ // {
535
+ // name: "Andrea",
536
+ // coords: {
537
+ // x: 2, y: 1
538
+ // }
539
+ // }
540
+ // );
522
541
 
523
542
  if (chatbot.log) {
524
543
  // console.log("tdcache:", chatbot.tdcache);
525
544
  console.log("requestId:", requestId);
526
545
  console.log("KEY:", TiledeskChatbotConst.REQ_PROJECT_ID_KEY);
527
- console.log("TiledeskChatbot:", TiledeskChatbot);
546
+ // console.log("TiledeskChatbot:", TiledeskChatbot);
528
547
  let proj_ = await chatbot.getParameter(TiledeskChatbotConst.REQ_PROJECT_ID_KEY);
529
548
  console.log("request parameter proj_:", proj_);
530
549
  const all_parameters = await chatbot.allParameters();
531
550
  for (const [key, value] of Object.entries(all_parameters)) {
532
551
  // const value = all_parameters[key];
533
552
  const value_type = typeof value;
534
- if (chatbot.log) {console.log("request parameter:", key, "value:", value, "type:", value_type)}
553
+ if (chatbot.log) {console.log("REQUEST ATTRIBUTE:", key, "VALUE:", value, "TYPE:", value_type)}
535
554
  }
536
555
  }
537
556
  } catch(error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-tybot-connector",
3
- "version": "0.2.27",
3
+ "version": "0.2.29",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -25,6 +25,7 @@ const { DirCondition } = require('./directives/DirCondition');
25
25
  const { DirJSONCondition } = require('./directives/DirJSONCondition');
26
26
  const { DirAssign } = require('./directives/DirAssign');
27
27
  const { DirSetAttribute } = require('./directives/DirSetAttribute');
28
+ const { DirSetAttributeV2 } = require('./directives/DirSetAttributeV2');
28
29
  const { DirWebRequest } = require('./directives/DirWebRequest');
29
30
  const { DirWebRequestV2 } = require('./directives/DirWebRequestV2');
30
31
  const { DirCode } = require('./directives/DirCode');
@@ -39,6 +40,7 @@ const { DirRandomReply } = require('./directives/DirRandomReply');
39
40
  const { DirGptTask } = require('./directives/DirGptTask');
40
41
  const { DirForm } = require('./directives/DirForm');
41
42
  const { DirCaptureUserReply } = require('./directives/DirCaptureUserReply');
43
+ const { DirMake } = require('./directives/DirMake');
42
44
 
43
45
  class DirectivesChatbotPlug {
44
46
 
@@ -370,6 +372,13 @@ class DirectivesChatbotPlug {
370
372
  this.process(next_dir);
371
373
  });
372
374
  }
375
+ else if (directive_name === Directives.SET_ATTRIBUTE_V2) {
376
+ // console.log("...DirSetAttribute");
377
+ new DirSetAttributeV2(context).execute(directive, async () => {
378
+ let next_dir = await this.nextDirective(this.directives);
379
+ this.process(next_dir);
380
+ });
381
+ }
373
382
  // else if (directive_name === Directives.WHEN_OPEN) {
374
383
  // // DEPRECATED
375
384
  // const whenOpenDir = new DirWhenOpen(
@@ -601,6 +610,12 @@ class DirectivesChatbotPlug {
601
610
  this.process(next_dir);
602
611
  })
603
612
  }
613
+ else if (directive_name === Directives.MAKE) {
614
+ new DirMake(context).execute(directive, async () => {
615
+ let next_dir = await this.nextDirective(this.directives);
616
+ this.process(next_dir);
617
+ })
618
+ }
604
619
  else {
605
620
  //console.log("Unhandled Post-message Directive:", directive_name);
606
621
  let next_dir = await this.nextDirective(this.directives);
@@ -0,0 +1,257 @@
1
+ const axios = require("axios").default;
2
+ const { TiledeskChatbot } = require("../../models/TiledeskChatbot");
3
+ const { Filler } = require("../Filler");
4
+ const { DirIntent } = require("./DirIntent");
5
+ let https = require("https");
6
+ require('dotenv').config();
7
+
8
+
9
+ class DirMake {
10
+
11
+ constructor(context) {
12
+ if (!context) {
13
+ throw new Error('context object is mandatory');
14
+ }
15
+ this.context = context;
16
+ this.tdcache = this.context.tdcache;
17
+ this.requestId = this.context.requestId;
18
+ this.log = context.log;
19
+ this.intentDir = new DirIntent(context);
20
+ }
21
+
22
+ execute(directive, callback) {
23
+ if (this.log) { console.log("DirMake directive: ", directive); }
24
+ let action;
25
+ if (directive.action) {
26
+ action = directive.action;
27
+ }
28
+ else {
29
+ console.error("DirMake Incorrect directive: ", JSON.stringify(directive));
30
+ callback();
31
+ return;
32
+ }
33
+ this.go(action, () => {
34
+ callback();
35
+ })
36
+ }
37
+
38
+ async go(action, callback) {
39
+ if (this.log) { console.log("DirMake action:", JSON.stringify(action)); }
40
+ if (!this.tdcache) {
41
+ console.error("Error: DirMake tdcache is mandatory");
42
+ callback();
43
+ return;
44
+ }
45
+ //console.log('DirMake work!');
46
+ let requestVariables = null;
47
+ requestVariables =
48
+ await TiledeskChatbot.allParametersStatic(
49
+ this.tdcache, this.requestId
50
+ )
51
+
52
+ if (this.log) {
53
+ const all_parameters = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
54
+ for (const [key, value] of Object.entries(all_parameters)) {
55
+ if (this.log) { console.log("DirMake request parameter:", key, "value:", value, "type:", typeof value) }
56
+ }
57
+ }
58
+
59
+ let webhook_url = action.url;
60
+ let bodyParameters = action.bodyParameters;
61
+ if (this.log) {
62
+ console.log("DirMake webhook_url: ", webhook_url);
63
+ console.log("DirMake bodyParameters: ", bodyParameters);
64
+ }
65
+ if (!bodyParameters || bodyParameters === '') {
66
+ console.error("DirMake ERROR - bodyParameters is undefined or null or empty string");
67
+ callback();
68
+ return;
69
+ }
70
+ if (!webhook_url || webhook_url === '') {
71
+ console.error("DirMake ERROR - webhook_url is undefined or null or empty string");
72
+ callback();
73
+ return;
74
+ }
75
+ let url;
76
+ try {
77
+ console.log('CIAOkkkk',bodyParameters)
78
+ let make_base_url = process.env.MAKE_ENDPOINT;
79
+ if (make_base_url) {
80
+ url = make_base_url + "/make/";
81
+ } else {
82
+ url = action.url;
83
+ }
84
+ console.log('Make url: ', url);
85
+ const filler = new Filler();
86
+
87
+
88
+ for (const [key, value] of Object.entries(bodyParameters)) {
89
+ if (this.log) {console.log("bodyParam:", key, "value:", value)}
90
+ let filled_value = filler.fill(value, requestVariables);
91
+ bodyParameters[key] = filled_value;
92
+ }
93
+
94
+ console.log('CIAO',bodyParameters)
95
+
96
+
97
+
98
+
99
+ // Condition branches
100
+ let trueIntent = action.trueIntent;
101
+ let falseIntent = action.falseIntent;
102
+ console.log('trueIntent',trueIntent)
103
+
104
+ if (this.log) { console.log("DirMake MakeEndpoint URL: ", make_base_url); }
105
+ const MAKE_HTTPREQUEST = {
106
+ url: url,
107
+ headers: {
108
+ 'Content-Type': 'application/json'
109
+ },
110
+ json: bodyParameters,
111
+ method: "POST"
112
+ }
113
+
114
+ if (this.log) { console.log("myrequest/DirMake MAKE_HTTPREQUEST", MAKE_HTTPREQUEST); }
115
+ this.#myrequest(
116
+ MAKE_HTTPREQUEST, async (err, resbody) => {
117
+ if (err) {
118
+ if (callback) {
119
+ console.error("myrequest/(httprequest) DirMake make err:", err);
120
+ let status = 404;
121
+ let error = 'Not found';
122
+ await this.#assignAttributes(action, status, error);
123
+ this.#executeCondition(false, trueIntent, null, falseIntent, null, () => {
124
+ callback(false); // continue the flow
125
+ });
126
+ callback();
127
+ }
128
+ } else if (callback) {
129
+ if (this.log) { console.log("myrequest/DirMake Make resbody: ", resbody); }
130
+ let status = 200;
131
+ let error = null;
132
+ await this.#assignAttributes(action, status, error);
133
+ await this.#executeCondition(true, trueIntent, null, falseIntent, null, () => {
134
+ callback(); // stop the flow
135
+ });
136
+ console.log('myrequest/status: ',status)
137
+ callback();
138
+ }
139
+ }
140
+ );
141
+ } catch(e) {
142
+ console.error('error: ', e)
143
+ }
144
+ }
145
+
146
+ async #assignAttributes(action, status, error) {
147
+ if (this.log) {
148
+ console.log("DirMake assignAttributes action:", action)
149
+ console.log("DirMake assignAttributes status:", status)
150
+ console.log("DirMake assignAttributes error:", error)
151
+ }
152
+ if (this.context.tdcache) {
153
+ if (action.assignStatusTo) {
154
+ await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignStatusTo, status);
155
+ }
156
+ if (action.assignErrorTo) {
157
+ await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignErrorTo, error);
158
+ }
159
+
160
+ // Debug log
161
+ if (this.log) {
162
+ const all_parameters = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
163
+ for (const [key, value] of Object.entries(all_parameters)) {
164
+ if (this.log) { console.log("DirMake request parameter:", key, "value:", value, "type:", typeof value) }
165
+ }
166
+ }
167
+ }
168
+ }
169
+
170
+ #myrequest(options, callback) {
171
+ if (this.log) {
172
+ console.log("API URL:", options.url);
173
+ console.log("** Options:", JSON.stringify(options));
174
+ }
175
+ let axios_options = {
176
+ url: options.url,
177
+ method: options.method,
178
+ params: options.params,
179
+ headers: options.headers
180
+ }
181
+ if (options.json !== null) {
182
+ axios_options.data = options.json
183
+ }
184
+ if (this.log) {
185
+ console.log("axios_options:", JSON.stringify(axios_options));
186
+ }
187
+ if (options.url.startsWith("https:")) {
188
+ const httpsAgent = new https.Agent({
189
+ rejectUnauthorized: false,
190
+ });
191
+ axios_options.httpsAgent = httpsAgent;
192
+ }
193
+ axios(axios_options)
194
+ .then((res) => {
195
+ if (this.log) {
196
+ console.log("Response for url:", options.url);
197
+ console.log("Response status:", res.status);
198
+ console.log("Response headers:\n", JSON.stringify(res.headers));
199
+ }
200
+ if (res && res.status == 200 && res.data) {
201
+ if (callback) {
202
+ callback(null, res.data);
203
+ }
204
+ }
205
+ else {
206
+ if (callback) {
207
+ callback(new Error("Response status is not 200"), null);
208
+ }
209
+ }
210
+ })
211
+ .catch((error) => {
212
+ // console.error("An error occurred:", JSON.stringify(error.data));
213
+ if (callback) {
214
+ callback(error, null);
215
+ }
216
+ });
217
+ }
218
+ async #executeCondition(result, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, callback) {
219
+ let trueIntentDirective = null;
220
+
221
+ if (trueIntent) {
222
+ //console.log('executeCondition/trueIntent',trueIntent)
223
+ trueIntentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
224
+ //console.log('executeCondition/trueIntentDirective',trueIntentDirective)
225
+ //console.log('executeCondition/trueIntentAttributes',trueIntentAttributes)
226
+ }
227
+ let falseIntentDirective = null;
228
+ if (falseIntent) {
229
+ falseIntentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
230
+ }
231
+ if (this.log) {console.log('DirMake executeCondition/result',result)}
232
+ if (result === true) {
233
+ if (trueIntentDirective) {
234
+ this.intentDir.execute(trueIntentDirective, () => {
235
+ callback();
236
+ });
237
+ }
238
+ else {
239
+ if (this.log) {console.log("No trueIntentDirective specified");}
240
+ callback();
241
+ }
242
+ }
243
+ else {
244
+ if (falseIntentDirective) {
245
+ this.intentDir.execute(falseIntentDirective, () => {
246
+ callback();
247
+ });
248
+ }
249
+ else {
250
+ if (this.log) {console.log("No falseIntentDirective specified");}
251
+ callback();
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ module.exports = { DirMake }
@@ -0,0 +1,190 @@
1
+ const { TiledeskChatbot } = require('../../models/TiledeskChatbot');
2
+ const { TiledeskExpression } = require('../../TiledeskExpression');
3
+ const { TiledeskMath } = require('../../TiledeskMath');
4
+ const { TiledeskString } = require('../../TiledeskString');
5
+ const { Filler } = require('../Filler');
6
+ const validate = require('jsonschema').validate;
7
+
8
+ const schema = {
9
+ "type": "object",
10
+ "properties": {
11
+ "_tdActionType": {
12
+ "type": "string",
13
+ "enum": ["setattribute"]
14
+ },
15
+ "_tdActionId": {
16
+ "type": ["string", "null"]
17
+ },
18
+ "_tdActionTitle": {
19
+ "type": ["string", "null"]
20
+ },
21
+ "destination": {
22
+ "type": "string",
23
+ },
24
+ "operation": {
25
+ "type": "object",
26
+ "properties": {
27
+ "operators": {
28
+ "type": "array",
29
+ "items": {
30
+ "type": "string",
31
+ "enum": ["addAsNumber", "addAsString", "subtractAsNumber", "multiplyAsNumber", "divideAsNumber"]
32
+ }
33
+ },
34
+
35
+ "operands": {
36
+ "type": "array",
37
+ "minItems": 1,
38
+ "items": {
39
+ "type": "object",
40
+ "properties": {
41
+ "value": {
42
+ "type": "string"
43
+ },
44
+ "isVariable": {
45
+ "type": "boolean"
46
+ },
47
+ "function": {
48
+ "type": "string",
49
+ "enum": ["capitalizeAsString", "upperCaseAsString", "lowerCaseAsString", "absAsNumber", "ceilAsNumber", "floorAsNumber", "roundAsNumber"]
50
+ }
51
+ },
52
+ "required": ["value", "isVariable"],
53
+ "additionalProperties": false,
54
+ "if": {
55
+ "properties": { "isVariable": { "const": true } },
56
+ },
57
+ "then": {
58
+ "properties": { "value": { "pattern": "^[a-zA-Z_]*[.]*[a-zA-Z_]+[a-zA-Z0-9_]*$" } }
59
+ }
60
+ }
61
+ }
62
+ },
63
+ "required": ["operands"],
64
+ "additionalProperties": false
65
+ }
66
+ },
67
+ "required": ["_tdActionType", "destination", "operation"],
68
+ "additionalProperties": false
69
+ };
70
+
71
+
72
+ class DirSetAttributeV2 {
73
+
74
+ constructor(context) {
75
+ if (!context) {
76
+ throw new Error('context object is mandatory.');
77
+ }
78
+ this.context = context;
79
+ this.tdcache = context.tdcache;
80
+ this.log = context.log;
81
+ }
82
+
83
+ execute(directive, callback) {
84
+ let action;
85
+ if (directive.action) {
86
+ action = directive.action
87
+ }
88
+ else {
89
+ callback();
90
+ return;
91
+ }
92
+ // console.log("go DirAssign with action:", action);
93
+ this.go(action, () => {
94
+ callback();
95
+ });
96
+ }
97
+
98
+ async go(action, callback) {
99
+ console.log("(DirSetAttribute) action before filling:", JSON.stringify(action));
100
+ if (action && action.operation && action.operation.operands) {
101
+ console.log("filling in setattribute...");
102
+ await this.fillValues(action.operation.operands);
103
+ }
104
+ console.log("filled in setattribute:", action.operation);
105
+ // let res = validate(action, schema);
106
+ // if (res.errors) {
107
+ // console.log("(DirSetAttribute) failed validation action:", JSON.stringify(action));
108
+ // console.log("DirSetAttribute validation errors:", res.errors);
109
+ // }
110
+ // if (!res.valid) {
111
+ // if (this.log) {console.error("(DirSetAttribute) Invalid action:", res.errors)};
112
+ // callback();
113
+ // return;
114
+ // }
115
+ if (action.operation.operators === undefined && action.operation.operands.length !== 1) {
116
+ if (this.log) {console.error("(DirSetAttribute) Invalid action: operators === undefined && operands.length !== 1")};
117
+ callback();
118
+ return;
119
+ }
120
+ if (action.operation.operators !== undefined && action.operation.operators.length !== action.operation.operands.length - 1) {
121
+ if (this.log) {console.error("(DirSetAttribute) Invalid action: operators.length !== operands.length - 1")};
122
+ callback();
123
+ return;
124
+ }
125
+ // if (action && action.operation && action.operation.operands) {
126
+ // console.log("filling in setattribute...");
127
+ // await this.fillValues(action.operation.operands);
128
+ // }
129
+ console.log("dirsetattribute, action.operation.operands:", action.operation.operands);
130
+ const expression = TiledeskExpression.JSONOperationToExpression(action.operation.operators, action.operation.operands);
131
+ const attributes = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
132
+ console.log("dirsetattribute, attributes:", attributes);
133
+ attributes.TiledeskMath = TiledeskMath;
134
+ attributes.TiledeskString = TiledeskString;
135
+ const result = new TiledeskExpression().evaluateJavascriptExpression(expression, attributes);
136
+ console.log("filling in setattribute, result:", result);
137
+ await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.destination, result);
138
+ callback();
139
+ }
140
+
141
+ async fillValues(operands) {
142
+ // operation: {
143
+ // operators: ["addAsNumber", "subtractAsNumber", "divideAsNumber", "multiplyAsNumber"],
144
+ // operands: [
145
+ // {
146
+ // value: "previous",
147
+ // isVariable: true
148
+ // },
149
+ // {
150
+ // value: "temp",
151
+ // isVariable: true,
152
+ // function: "floorAsNumber"
153
+ // },
154
+ // {
155
+ // value: "real",
156
+ // isVariable: true,
157
+ // function: "absAsNumber"
158
+ // },
159
+ // {
160
+ // value: "input",
161
+ // isVariable: true
162
+ // },
163
+ // {
164
+ // value: "2",
165
+ // isVariable: false
166
+ // }
167
+ // ]
168
+ try {
169
+ if (this.tdcache) {
170
+ // console.log("tdcache in setattribute...", this.tdcache);
171
+ const requestAttributes =
172
+ await TiledeskChatbot.allParametersStatic(this.tdcache, this.context.requestId);
173
+ // console.log("requestAttributes in setattribute...", requestAttributes);
174
+ const filler = new Filler();
175
+ operands.forEach(operand => {
176
+ if (!operand.isVariable) {
177
+ console.log("setattribute, liquid operand:", operand);
178
+ operand.value = filler.fill(operand.value, requestAttributes);
179
+ console.log("setattribute, final operand:", operand);
180
+ }
181
+ });
182
+ }
183
+ }
184
+ catch(error) {
185
+ console.error("Error while filling operands:", error);
186
+ }
187
+ }
188
+ }
189
+
190
+ module.exports = { DirSetAttributeV2 };
@@ -22,6 +22,7 @@ class Directives {
22
22
  static FUNCTION_VALUE = "functionvalue";
23
23
  static JSON_CONDITION = "jsoncondition";
24
24
  static SET_ATTRIBUTE = "setattribute";
25
+ static SET_ATTRIBUTE_V2 = "setattribute-v2";
25
26
  static REPLY = 'reply';
26
27
  static RANDOM_REPLY = 'randomreply';
27
28
  static CODE = 'code';
@@ -31,6 +32,7 @@ class Directives {
31
32
  static FORM = "form";
32
33
  static CAPTURE_USER_REPLY = "capture_user_reply";
33
34
  static QAPLA = 'qapla';
35
+ static MAKE = 'make';
34
36
 
35
37
  // static WHEN_ONLINE_MOVE_TO_AGENT = "whenonlinemovetoagent"; // DEPRECATED?
36
38
  // static WHEN_OFFLINE_HOURS = "whenofflinehours"; // DEPRECATED // adds a message on top of the original message when offline hours opts: --replace