@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 +5 -1
- package/package.json +1 -1
- package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +20 -1
- package/tiledeskChatbotPlugs/directives/DirAskGPT.js +17 -0
- package/tiledeskChatbotPlugs/directives/DirAskGPTV2.js +1 -4
- package/tiledeskChatbotPlugs/directives/DirCustomerio.js +302 -0
- package/tiledeskChatbotPlugs/directives/DirGptTask.js +75 -5
- package/tiledeskChatbotPlugs/directives/DirHubspot.js +310 -0
- package/tiledeskChatbotPlugs/directives/DirMake.js +2 -2
- package/tiledeskChatbotPlugs/directives/Directives.js +2 -0
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
|
-
-
|
|
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
|
@@ -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.
|
|
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("
|
|
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
|