@tiledesk/tiledesk-tybot-connector 0.2.50 → 0.2.51

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
@@ -6,8 +6,12 @@ available on:
6
6
  ▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
7
7
 
8
8
  # v0.2.50
9
- - Added AskGPTV2 action
9
+ - Improved AskGPTV2 action
10
10
  - Added Hubspot action
11
+ - Added Customerio action (hidden)
12
+
13
+ # v0.2.50
14
+ - Added AskGPTV2 action
11
15
 
12
16
  # v0.2.49
13
17
  - resplacebotv2, added "/" + blockName (so the blockname will be implicitly executed), removing the need to specify the "/" in the body of the replacebot editor
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-tybot-connector",
3
- "version": "0.2.50",
3
+ "version": "0.2.51",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -42,6 +42,8 @@ const { DirForm } = require('./directives/DirForm');
42
42
  const { DirCaptureUserReply } = require('./directives/DirCaptureUserReply');
43
43
  const { DirMake } = require('./directives/DirMake');
44
44
  const { DirReplaceBotV2 } = require('./directives/DirReplaceBotV2');
45
+ const { DirHubspot } = require('./directives/DirHubspot');
46
+ const { DirCustomerio } = require('./directives/DirCustomerio');
45
47
  const { DirAskGPTV2 } = require('./directives/DirAskGPTV2');
46
48
 
47
49
  class DirectivesChatbotPlug {
@@ -608,7 +610,6 @@ class DirectivesChatbotPlug {
608
610
  });
609
611
  }
610
612
  else if (directive_name === Directives.ASK_GPT_V2) {
611
-
612
613
  new DirAskGPTV2(context).execute(directive, async (stop) => {;
613
614
  if (context.log) { console.log("AskGPTV2 stop?", stop);}
614
615
  if (stop == true) {
@@ -666,6 +667,24 @@ class DirectivesChatbotPlug {
666
667
  }
667
668
  })
668
669
  }
670
+ else if (directive_name === Directives.HUBSPOT) {
671
+ new DirHubspot(context).execute(directive, async (stop) => {
672
+ if (context.log) { console.log("Hubspot stop?", stop);}
673
+ if (stop == true) {
674
+ if (context.log) { console.log("Stopping Actions on:", JSON.stringify(directive));}
675
+ this.theend();
676
+ } else {
677
+ let next_dir = await this.nextDirective(this.directives);
678
+ this.process(next_dir);
679
+ }
680
+ })
681
+ }
682
+ else if (directive_name === Directives.CUSTOMERIO) {
683
+ new DirCustomerio(context).execute(directive, async () => {
684
+ let next_dir = await this.nextDirective(this.directives);
685
+ this.process(next_dir);
686
+ })
687
+ }
669
688
  else {
670
689
  //console.log("Unhandled Post-message Directive:", directive_name);
671
690
  let next_dir = await this.nextDirective(this.directives);
@@ -42,6 +42,7 @@ class DirAskGPT {
42
42
  return;
43
43
  }
44
44
 
45
+ let publicKey = false;
45
46
  let trueIntent = action.trueIntent;
46
47
  let falseIntent = action.falseIntent;
47
48
  let trueIntentAttributes = action.trueIntentAttributes;
@@ -103,6 +104,7 @@ class DirAskGPT {
103
104
  if (!key) {
104
105
  if (this.log) { console.log("DirGptTask - Retrieve public gptkey")}
105
106
  key = process.env.GPTKEY;
107
+ publicKey = true;
106
108
  }
107
109
 
108
110
  if (!key) {
@@ -117,6 +119,15 @@ class DirAskGPT {
117
119
  return;
118
120
  }
119
121
 
122
+ if (publicKey === true) {
123
+ let keep_going = await this.checkQuoteAvailability(server_base_url);
124
+ if (keep_going === false) {
125
+ if (this.log) { console.log("DirGptTask - Quota exceeded for tokens. Skip the action")}
126
+ callback();
127
+ return;
128
+ }
129
+ }
130
+
120
131
  let json = {
121
132
  question: filled_question,
122
133
  kbid: action.kbid,
@@ -153,6 +164,12 @@ class DirAskGPT {
153
164
  }
154
165
  }
155
166
  else if (resbody.success === true) {
167
+
168
+ // if (publicKey === true) {
169
+ // let token_usage = resbody.usage.total_tokens;
170
+ // this.updateQuote(server_base_url, token_usage);
171
+ // }
172
+
156
173
  if (trueIntent) {
157
174
  await this.#executeCondition(true, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
158
175
  callback(true);
@@ -165,7 +165,7 @@ class DirAskGPTV2 {
165
165
  }
166
166
  if (this.log) { console.log("DirAskGPT resbody:", resbody); }
167
167
  let answer = resbody.answer;
168
- let source = resbody.source_url;
168
+ let source = resbody.source;
169
169
  await this.#assignAttributes(action, answer, source);
170
170
 
171
171
  if (err) {
@@ -257,10 +257,7 @@ class DirAskGPTV2 {
257
257
  if (action.assignReplyTo && answer) {
258
258
  await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignReplyTo, answer);
259
259
  }
260
- // console.log("--> action.assignSourceTo: ", action.assignSourceTo)
261
- // console.log("--> source: ", source)
262
260
  if (action.assignSourceTo && source) {
263
- // console.log("--> source: ", source)
264
261
  await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignSourceTo, source);
265
262
  }
266
263
  // Debug log
@@ -0,0 +1,302 @@
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 DirCustomerio {
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
+ if (this.log) {console.log('LOG: ', this.log)};
21
+ }
22
+
23
+ execute(directive, callback) {
24
+ if (this.log) { console.log("DirCustomerio directive: ", directive); }
25
+ let action;
26
+ if (directive.action) {
27
+ action = directive.action;
28
+ }
29
+ else {
30
+ console.error("DirCustomerio Incorrect directive: ", JSON.stringify(directive));
31
+ callback();
32
+ return;
33
+ }
34
+ this.go(action, () => {
35
+ callback();
36
+ })
37
+ }
38
+
39
+ async go(action, callback) {
40
+ if (this.log) { console.log("DirCustomerio action:", JSON.stringify(action)); }
41
+ let token = action.token;
42
+ let formid = action.formid;
43
+ let bodyParameters = action.bodyParameters;
44
+
45
+ let trueIntent = action.trueIntent;
46
+ let falseIntent = action.falseIntent;
47
+ if (this.log) {console.log('DirCustomerio trueIntent',trueIntent)}
48
+ if (!this.tdcache) {
49
+ console.error("Error: DirCustomerio tdcache is mandatory");
50
+ callback();
51
+ return;
52
+ }
53
+ console.log('DirCustomerio work!');
54
+ let requestVariables = null;
55
+ requestVariables =
56
+ await TiledeskChatbot.allParametersStatic(
57
+ this.tdcache, this.requestId
58
+ )
59
+
60
+ if (this.log) {
61
+ const all_parameters = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
62
+ for (const [key, value] of Object.entries(all_parameters)) {
63
+ if (this.log) { console.log("DirCustomerio request parameter:", key, "value:", value, "type:", typeof value) }
64
+ }
65
+ }
66
+
67
+ //let token = action.token;
68
+ //let bodyParameters = action.bodyParameters;
69
+ if (this.log) {
70
+ console.log("DirCustomerio token: ", token);
71
+ console.log("DirCustomerio formid: ", formid);
72
+ console.log("DirCustomerio bodyParameters: ", bodyParameters);
73
+ }
74
+ if (!bodyParameters || bodyParameters === '') {
75
+ if (this.log) {console.error("DirCustomerio ERROR - bodyParameters is undefined or null or empty string")};
76
+ callback();
77
+ return;
78
+ }
79
+ if (!token || token === '') {
80
+ if (this.log) {console.error("DirCustomerio ERROR - token is undefined or null or empty string:")};
81
+ let status = 422;
82
+ let error = 'Missing customerio access token';
83
+ await this.#assignAttributes(action, status, error);
84
+ this.#executeCondition(false, trueIntent, null, falseIntent, null, () => {
85
+ callback(); // stop the flow
86
+ });
87
+ return;
88
+ }
89
+ let url;
90
+ try {
91
+ // CUSTOMERIO_ENDPONT
92
+ let customer_base_url = process.env.CUSTOMERIO_ENDPONT;
93
+ if (customer_base_url) {
94
+ url = customer_base_url + "/api/v1/forms/"+formid+"/submit";
95
+ if (this.log) {console.log('DirCustomerio customer_base_url: ',url)};
96
+ } else {
97
+ url = "https://track-eu.customer.io/api/v1/forms/"+formid+"/submit";
98
+ //console.log('DirCustomerio url: ',url);
99
+ }
100
+ // CUSTOMER ACCESS TOKEN
101
+ //let token = action.token;
102
+ if (this.log) {
103
+ console.log('DirCustomerio url: ',url);
104
+ console.log('DirCustomerio access token: ',token);
105
+ }
106
+
107
+ const filler = new Filler();
108
+ for (const [key, value] of Object.entries(bodyParameters)) {
109
+ if (this.log) {console.log("bodyParam:", key, "value:", value)}
110
+ let filled_value = filler.fill(value, requestVariables);
111
+ bodyParameters[key] = filled_value;
112
+ }
113
+ if (this.log) {console.log('DirCustomerio bodyParameters filler: ',bodyParameters)}
114
+
115
+
116
+
117
+ // Condition branches
118
+ //let trueIntent = action.trueIntent;
119
+ //let falseIntent = action.falseIntent;
120
+ //console.log('DirCustomerio trueIntent',trueIntent)
121
+
122
+ if (this.log) { console.log("DirCustomerio Customerio access token: ", token); }
123
+ const CUSTOMERIO_HTTPREQUEST = {
124
+ url: url,
125
+ headers: {
126
+ 'authorization': 'Basic ' + token,
127
+ 'Content-Type': 'application/json',
128
+ 'Cache-Control': 'no-cache',
129
+ 'User-Agent': 'TiledeskBotRuntime',
130
+ 'Accept': '*/*'
131
+ },
132
+ json: bodyParameters,
133
+ method: "POST"
134
+ }
135
+
136
+ if (this.log) { console.log("myrequest/DirCustomerio CUSTOMERIO_HTTPREQUEST", JSON.stringify(CUSTOMERIO_HTTPREQUEST)); }
137
+ this.#myrequest(
138
+ CUSTOMERIO_HTTPREQUEST, async (err, resbody) => {
139
+ if (err) {
140
+ if (callback) {
141
+ if (this.log) {
142
+ console.error("respose/(httprequest) DirCustomerio err response:", err)
143
+ };
144
+ let status = null;
145
+ let error;
146
+ //-------------------------------------------------------
147
+ // if (err.response &&
148
+ // err.response.status) {
149
+ // status = err.response.status;
150
+ // }
151
+ // if (err.response &&
152
+ // err.response.data &&
153
+ // err.response.data.meta && err.response.data.meta.error) {
154
+ // error = err.response.data.meta.error;
155
+ // }
156
+
157
+ //-------------------------------------------------------
158
+ if (this.log) {
159
+ console.log("FALSE");
160
+ //console.error("respose/(httprequest) DirCustomerio err data status:", status);
161
+ //console.error("respose/(httprequest) DirCustomerio err data error:", error);
162
+ console.error("respose/(httprequest) DirCustomerio err action:", action);}
163
+ await this.#assignAttributes(action, status, error);
164
+ this.#executeCondition(false, trueIntent, null, falseIntent, null, () => {
165
+ callback(false); // continue the flow
166
+ });
167
+ callback();
168
+ }
169
+ } else if (callback) {
170
+ if (this.log) { console.log("respose/DirCustomerio Customerio resbody: ", JSON.stringify(resbody, null, 2)); }
171
+ console.log("TRUE");
172
+ let status = 204;
173
+ let error = null;
174
+ await this.#assignAttributes(action, status, error);
175
+ await this.#executeCondition(true, trueIntent, null, falseIntent, null, () => {
176
+ callback(); // stop the flow
177
+ });
178
+ if (this.log) { console.log('respose/status: ',status)}
179
+ //callback();
180
+ }
181
+ }
182
+ );
183
+ } catch(e) {
184
+ console.error('error: ', e)
185
+ }
186
+ }
187
+
188
+ async #assignAttributes(action, status, error) {
189
+ if (this.log) {
190
+ console.log("DirCustomerio assignAttributes action:", action)
191
+ console.log("DirCustomerio assignAttributes status:", status)
192
+ console.log("DirCustomerio assignAttributes error:", error)
193
+ }
194
+ if (this.context.tdcache) {
195
+ if (action.assignStatusTo) {
196
+ await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignStatusTo, status);
197
+ }
198
+ if (action.assignErrorTo) {
199
+ await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignErrorTo, error);
200
+ }
201
+
202
+ // Debug log
203
+ if (this.log) {
204
+ const all_parameters = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
205
+ for (const [key, value] of Object.entries(all_parameters)) {
206
+ if (this.log) { console.log("DirCustomerio request parameter:", key, "value:", value, "type:", typeof value) }
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ #myrequest(options, callback) {
213
+ if (this.log) {
214
+ console.log("** API URL:", options.url);
215
+ console.log("** Options:", JSON.stringify(options));
216
+ }
217
+ let axios_options = {
218
+ url: options.url,
219
+ method: options.method,
220
+ params: options.params,
221
+ headers: options.headers
222
+ }
223
+ if (options.json !== null) {
224
+ axios_options.data = options.json
225
+ }
226
+ if (this.log) {
227
+ console.log("axios_options:", JSON.stringify(axios_options));
228
+ }
229
+ if (options.url.startsWith("https:")) {
230
+ const httpsAgent = new https.Agent({
231
+ rejectUnauthorized: false,
232
+ });
233
+ axios_options.httpsAgent = httpsAgent;
234
+ }
235
+ axios(axios_options)
236
+ .then((res) => {
237
+ if (this.log) {
238
+ console.log("Response for url:", options.url);
239
+ console.log("Response:", res.config.data);
240
+ console.log("Response status:", res.status);
241
+ console.log("Response headers:\n", JSON.stringify(res.headers));
242
+ }
243
+ if (res && res.status == 204) {
244
+ if (callback) {
245
+ callback(null, res.config.data);
246
+ }
247
+ }
248
+ else {
249
+ if (callback) {
250
+ callback(new Error("Response status is not 204"), null);
251
+ }
252
+ }
253
+ })
254
+ .catch((error) => {
255
+ if (this.log) {console.error("An error occurred:", JSON.stringify(error.message))};
256
+ if (callback) {
257
+ callback(error, null);
258
+ }
259
+ });
260
+ }
261
+ async #executeCondition(result, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, callback) {
262
+ let trueIntentDirective = null;
263
+
264
+ if (trueIntent) {
265
+ //console.log('executeCondition/trueIntent',trueIntent)
266
+ trueIntentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
267
+ //console.log('executeCondition/trueIntentDirective',trueIntentDirective)
268
+ //console.log('executeCondition/trueIntentAttributes',trueIntentAttributes)
269
+ }
270
+ let falseIntentDirective = null;
271
+ if (falseIntent) {
272
+ falseIntentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
273
+ }
274
+ if (this.log) {console.log('DirCustomerio executeCondition/result',result)}
275
+ if (result === true) {
276
+ if (trueIntentDirective) {
277
+ console.log("--> TRUE")
278
+ this.intentDir.execute(trueIntentDirective, () => {
279
+ callback();
280
+ });
281
+ }
282
+ else {
283
+ if (this.log) {console.log("No trueIntentDirective specified");}
284
+ callback();
285
+ }
286
+ }
287
+ else {
288
+ if (falseIntentDirective) {
289
+ console.log("--> FALSE");
290
+ this.intentDir.execute(falseIntentDirective, () => {
291
+ callback();
292
+ });
293
+ }
294
+ else {
295
+ if (this.log) {console.log("No falseIntentDirective specified");}
296
+ callback();
297
+ }
298
+ }
299
+ }
300
+ }
301
+
302
+ module.exports = { DirCustomerio }
@@ -42,6 +42,7 @@ class DirGptTask {
42
42
  return;
43
43
  }
44
44
 
45
+ let publicKey = false;
45
46
  let trueIntent = action.trueIntent;
46
47
  let falseIntent = action.falseIntent;
47
48
  let trueIntentAttributes = action.trueIntentAttributes;
@@ -93,7 +94,6 @@ class DirGptTask {
93
94
  }
94
95
 
95
96
  let key = await this.getKeyFromIntegrations(server_base_url);
96
-
97
97
  if (!key) {
98
98
  if (this.log) { console.log("DirGptTask - Key not found in Integrations. Searching in kb settings..."); }
99
99
  key = await this.getKeyFromKbSettings(server_base_url);
@@ -102,12 +102,12 @@ class DirGptTask {
102
102
  if (!key) {
103
103
  if (this.log) { console.log("DirGptTask - Retrieve public gptkey")}
104
104
  key = process.env.GPTKEY;
105
+ publicKey = true;
105
106
  }
106
107
 
107
108
  if (!key) {
108
109
  console.error("DirGptTask gptkey is mandatory");
109
110
  await this.#assignAttributes(action, answer);
110
-
111
111
  if (falseIntent) {
112
112
  await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
113
113
  callback(true);
@@ -117,6 +117,15 @@ class DirGptTask {
117
117
  return;
118
118
  }
119
119
 
120
+ if (publicKey === true) {
121
+ let keep_going = await this.checkQuoteAvailability(server_base_url);
122
+ if (keep_going === false) {
123
+ if (this.log) { console.log("DirGptTask - Quota exceeded for tokens. Skip the action")}
124
+ callback();
125
+ return;
126
+ }
127
+ }
128
+
120
129
  let json = {
121
130
  model: action.model,
122
131
  messages: [
@@ -168,6 +177,12 @@ class DirGptTask {
168
177
  // check if answer is a json
169
178
  let answer_json = await this.convertToJson(answer);
170
179
  await this.#assignAttributes(action, answer_json);
180
+
181
+ if (publicKey === true) {
182
+ let token_usage = resbody.usage.total_tokens;
183
+ this.updateQuote(server_base_url, token_usage);
184
+ }
185
+
171
186
  if (trueIntent) {
172
187
  await this.#executeCondition(true, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
173
188
  callback(true);
@@ -245,9 +260,6 @@ class DirGptTask {
245
260
  if (action.assignReplyTo && answer) {
246
261
  await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignReplyTo, answer);
247
262
  }
248
- // if (action.assignSourceTo && source) {
249
- // await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignSourceTo, source);
250
- // }
251
263
  // Debug log
252
264
  if (this.log) {
253
265
  const all_parameters = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
@@ -366,6 +378,64 @@ class DirGptTask {
366
378
  })
367
379
  }
368
380
 
381
+ async checkQuoteAvailability(server_base_url) {
382
+ return new Promise((resolve) => {
383
+
384
+ const HTTPREQUEST = {
385
+ url: server_base_url + "/" + this.context.projectId + "/quotes/tokens",
386
+ headers: {
387
+ 'Content-Type': 'application/json',
388
+ 'Authorization': 'JWT ' + this.context.token
389
+ },
390
+ method: "GET"
391
+ }
392
+ if (this.log) { console.log("DirGptTask check quote availability HTTPREQUEST", HTTPREQUEST); }
393
+
394
+ this.#myrequest(
395
+ HTTPREQUEST, async (err, resbody) => {
396
+ if (err) {
397
+ console.error("(httprequest) DirGptTask Check quote availability err: ", err);
398
+ resolve(true)
399
+ } else {
400
+ if (resbody.isAvailable === true) {
401
+ resolve(true)
402
+ } else {
403
+ resolve(false)
404
+ }
405
+ }
406
+ }
407
+ )
408
+ })
409
+ }
410
+
411
+ async updateQuote(server_base_url, tokens) {
412
+ return new Promise((resolve) => {
413
+
414
+ const HTTPREQUEST = {
415
+ url: server_base_url + "/" + this.context.projectId + "/quotes/incr/tokens",
416
+ headers: {
417
+ 'Content-Type': 'application/json',
418
+ 'Authorization': 'JWT ' + this.context.token
419
+ },
420
+ json: { tokens: tokens },
421
+ method: "POST"
422
+ }
423
+ if (this.log) { console.log("DirGptTask check quote availability HTTPREQUEST", HTTPREQUEST); }
424
+
425
+ this.#myrequest(
426
+ HTTPREQUEST, async (err, resbody) => {
427
+ if (err) {
428
+ console.error("(httprequest) DirGptTask Increment tokens quote err: ", err);
429
+ rejects(false)
430
+ } else {
431
+ console.log("(httprequest) DirGptTask Increment token quote resbody: ", resbody);
432
+ resolve(true);
433
+ }
434
+ }
435
+ )
436
+ })
437
+ }
438
+
369
439
  }
370
440
 
371
441
  module.exports = { DirGptTask }
@@ -0,0 +1,310 @@
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 DirHubspot {
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.intentDir = new DirIntent(context);
19
+ this.log = context.log;
20
+ }
21
+
22
+ execute(directive, callback) {
23
+ if (this.log) { console.log("DirHubspot directive: ", directive); }
24
+ let action;
25
+ if (directive.action) {
26
+ action = directive.action;
27
+ }
28
+ else {
29
+ console.error("DirHubspot Incorrect directive: ", JSON.stringify(directive));
30
+ callback();
31
+ return;
32
+ }
33
+ this.go(action, (stop) => {
34
+ callback(stop);
35
+ })
36
+ }
37
+
38
+ async go(action, callback) {
39
+ if (this.log) { console.log("DirHubspot action:", JSON.stringify(action)); }
40
+ if (!this.tdcache) {
41
+ console.error("Error: DirHubspot tdcache is mandatory");
42
+ callback();
43
+ return;
44
+ }
45
+
46
+ let trueIntent = action.trueIntent;
47
+ let falseIntent = action.falseIntent;
48
+ let trueIntentAttributes = action.trueIntentAttributes;
49
+ let falseIntentAttributes = action.falseIntentAttributes;
50
+
51
+ if (this.log) {
52
+ console.log("DirAskGPT trueIntent", trueIntent)
53
+ console.log("DirAskGPT falseIntent", falseIntent)
54
+ console.log("DirAskGPT trueIntentAttributes", trueIntentAttributes)
55
+ console.log("DirAskGPT falseIntentAttributes", falseIntentAttributes)
56
+ }
57
+
58
+ let requestVariables = null;
59
+ requestVariables =
60
+ await TiledeskChatbot.allParametersStatic(
61
+ this.tdcache, this.requestId
62
+ )
63
+
64
+ //let token = action.token;
65
+ let bodyParameters = action.bodyParameters;
66
+ if (this.log) { console.log("DirHubspot bodyParameters: ", bodyParameters); }
67
+
68
+ if (!bodyParameters || bodyParameters === '') {
69
+ if (this.log) { console.error("DirHubspot ERROR - bodyParameters is undefined or null or empty string") };
70
+ callback();
71
+ return;
72
+ }
73
+
74
+ const server_base_url = process.env.API_ENDPOINT || process.env.API_URL;
75
+ const hubspot_base_url = process.env.HUBSPOT_ENDPOINT;
76
+ if (this.log) {
77
+ console.log("DirHubspot server_base_url ", server_base_url);
78
+ console.log("DirHubspot hubspot_base_url ", hubspot_base_url);
79
+ }
80
+
81
+ let key = await this.getKeyFromIntegrations(server_base_url);
82
+ if (!key) {
83
+ if (this.log) { console.log("DirGptTask - Key not found in Integrations."); }
84
+ if (falseIntent) {
85
+ await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
86
+ callback(true);
87
+ return;
88
+ }
89
+ }
90
+
91
+ const filler = new Filler();
92
+ for (const [key, value] of Object.entries(bodyParameters)) {
93
+ if (this.log) { console.log("bodyParam:", key, "value:", value) }
94
+ let filled_value = filler.fill(value, requestVariables);
95
+ bodyParameters[key] = filled_value;
96
+ }
97
+ if (this.log) { console.log('DirHubspot bodyParameters filler: ', bodyParameters) }
98
+
99
+ let json = {
100
+ inputs: [
101
+ { properties: bodyParameters, associations: [] }
102
+ ]
103
+ }
104
+ const HUBSPOT_HTTPREQUEST = {
105
+ url: hubspot_base_url + 'objects/contacts/batch/create',
106
+ headers: {
107
+ 'Content-Type': 'application/json',
108
+ 'Authorization': 'Bearer ' + key
109
+ },
110
+ json: json,
111
+ method: "POST"
112
+ }
113
+ if (this.log) { console.log("DirHubspot MAKE_HTTPREQUEST", JSON.stringify(HUBSPOT_HTTPREQUEST)); }
114
+
115
+ this.#myrequest(
116
+ HUBSPOT_HTTPREQUEST, async (err, resbody) => {
117
+ if (err) {
118
+ if (callback) {
119
+ if (this.log) {
120
+ console.error("(httprequest) DirHubspot err response:", err.response)
121
+ console.error("(httprequest) DirHubspot err data:", err.response.data)
122
+ };
123
+
124
+ let status = null;
125
+ let error;
126
+
127
+ if (err.response &&
128
+ err.response.status) {
129
+ status = err.response.status;
130
+ }
131
+
132
+ if (err.response &&
133
+ err.response.data &&
134
+ err.response.data.message) {
135
+ error = err.response.data.message;
136
+ }
137
+
138
+ if (this.log) {
139
+ console.error("(httprequest) DirHubspot err data status:", status);
140
+ console.error("(httprequest) DirHubspot err data error:", error);
141
+ }
142
+
143
+ await this.#assignAttributes(action, status, error);
144
+ if (falseIntent) {
145
+ await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
146
+ callback(true);
147
+ return;
148
+ }
149
+ callback();
150
+ return;
151
+ }
152
+ } else if (callback) {
153
+ if (this.log) { console.log("DirHubspot resbody: ", JSON.stringify(resbody, null, 2)); }
154
+
155
+ let status = 201;
156
+ let error = null;
157
+ await this.#assignAttributes(action, status, error);
158
+ if (trueIntent) {
159
+ await this.#executeCondition(true, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes)
160
+ callback(true);
161
+ return;
162
+ }
163
+ callback();
164
+ return;
165
+ }
166
+ }
167
+ );
168
+
169
+ }
170
+
171
+ async #assignAttributes(action, status, error) {
172
+ if (this.log) {
173
+ console.log("DirHubspot assignAttributes action:", action)
174
+ console.log("DirHubspot assignAttributes status:", status)
175
+ console.log("DirHubspot assignAttributes error:", error)
176
+ }
177
+ if (this.context.tdcache) {
178
+ if (action.assignStatusTo) {
179
+ await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignStatusTo, status);
180
+ }
181
+ if (action.assignErrorTo) {
182
+ await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignErrorTo, error);
183
+ }
184
+
185
+ // Debug log
186
+ if (this.log) {
187
+ const all_parameters = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
188
+ for (const [key, value] of Object.entries(all_parameters)) {
189
+ if (this.log) { console.log("DirHubspot request parameter:", key, "value:", value, "type:", typeof value) }
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ #myrequest(options, callback) {
196
+ if (this.log) {
197
+ console.log("** API URL:", options.url);
198
+ console.log("** Options:", JSON.stringify(options));
199
+ }
200
+ let axios_options = {
201
+ url: options.url,
202
+ method: options.method,
203
+ params: options.params,
204
+ headers: options.headers
205
+ }
206
+ if (options.json !== null) {
207
+ axios_options.data = options.json
208
+ }
209
+ if (this.log) {
210
+ console.log("axios_options:", JSON.stringify(axios_options));
211
+ }
212
+ if (options.url.startsWith("https:")) {
213
+ const httpsAgent = new https.Agent({
214
+ rejectUnauthorized: false,
215
+ });
216
+ axios_options.httpsAgent = httpsAgent;
217
+ }
218
+ axios(axios_options)
219
+ .then((res) => {
220
+ if (this.log) {
221
+ console.log("Response for url:", options.url);
222
+ console.log("Response headers:\n", JSON.stringify(res.headers));
223
+ }
224
+ if (res && (res.status == 200 || res.status == 201) && res.data) {
225
+ if (callback) {
226
+ callback(null, res.data);
227
+ }
228
+ }
229
+ else {
230
+ if (callback) {
231
+ callback(new Error("Response status is not 200"), null);
232
+ }
233
+ }
234
+ })
235
+ .catch((error) => {
236
+ if (callback) {
237
+ callback(error, null);
238
+ }
239
+ });
240
+ }
241
+
242
+ async #executeCondition(result, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, callback) {
243
+ let trueIntentDirective = null;
244
+
245
+ if (trueIntent) {
246
+ trueIntentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
247
+ }
248
+ let falseIntentDirective = null;
249
+ if (falseIntent) {
250
+ falseIntentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
251
+ }
252
+ if (this.log) { console.log('DirHubspot executeCondition/result', result) }
253
+ if (result === true) {
254
+ if (trueIntentDirective) {
255
+ this.intentDir.execute(trueIntentDirective, () => {
256
+ callback();
257
+ });
258
+ }
259
+ else {
260
+ if (this.log) { console.log("No trueIntentDirective specified"); }
261
+ callback();
262
+ }
263
+ }
264
+ else {
265
+ if (falseIntentDirective) {
266
+ this.intentDir.execute(falseIntentDirective, () => {
267
+ callback();
268
+ });
269
+ }
270
+ else {
271
+ if (this.log) { console.log("No falseIntentDirective specified"); }
272
+ callback();
273
+ }
274
+ }
275
+ }
276
+
277
+ async getKeyFromIntegrations(server_base_url) {
278
+ return new Promise((resolve) => {
279
+
280
+ const INTEGRATIONS_HTTPREQUEST = {
281
+ url: server_base_url + "/" + this.context.projectId + "/integration/name/hubspot",
282
+ headers: {
283
+ 'Content-Type': 'application/json',
284
+ 'Authorization': 'JWT ' + this.context.token
285
+ },
286
+ method: "GET"
287
+ }
288
+ if (this.log) { console.log("DirGptTask INTEGRATIONS_HTTPREQUEST ", INTEGRATIONS_HTTPREQUEST) }
289
+
290
+ this.#myrequest(
291
+ INTEGRATIONS_HTTPREQUEST, async (err, integration) => {
292
+ if (err) {
293
+ resolve(null);
294
+ } else {
295
+
296
+ if (integration &&
297
+ integration.value) {
298
+ resolve(integration.value.apikey)
299
+ }
300
+ else {
301
+ resolve(null)
302
+ }
303
+ }
304
+ })
305
+ })
306
+ }
307
+
308
+ }
309
+
310
+ module.exports = { DirHubspot }
@@ -86,8 +86,8 @@ class DirMake {
86
86
  }
87
87
 
88
88
  if (!webhook_url || webhook_url === '') {
89
- console.error("Error: DirMake Webhook Url is not defined");
90
- let status = 422;
89
+ if (this.log) {console.error("DirMake ERROR - webhook_url is undefined or null or empty string:")};
90
+ let status = 422;
91
91
  let error = 'Missing make webhook url';
92
92
  await this.#assignAttributes(action, status, error);
93
93
  if (falseIntent) {
@@ -35,6 +35,8 @@ class Directives {
35
35
  static QAPLA = 'qapla';
36
36
  static MAKE = 'make';
37
37
  static REPLACE_BOT_V2 = "replacebotv2";
38
+ static HUBSPOT = 'hubspot';
39
+ static CUSTOMERIO = 'customerio';
38
40
 
39
41
  // static WHEN_ONLINE_MOVE_TO_AGENT = "whenonlinemovetoagent"; // DEPRECATED?
40
42
  // static WHEN_OFFLINE_HOURS = "whenofflinehours"; // DEPRECATED // adds a message on top of the original message when offline hours opts: --replace