@tiledesk/tiledesk-tybot-connector 2.0.19 → 2.0.21-rc1
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 +27 -2
- package/Logger.js +3 -0
- package/TdCache.js +16 -2
- package/engine/mock/MockBotsDataSource.js +1 -2
- package/index.js +11 -3
- package/package.json +1 -1
- package/services/KbService.js +105 -0
- package/services/QuotasService.js +69 -0
- package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +29 -11
- package/tiledeskChatbotPlugs/directives/DirAskGPTV2.js +11 -90
- package/tiledeskChatbotPlugs/directives/DirReply.js +2 -0
- package/tiledeskChatbotPlugs/directives/DirWebRequestV2.js +1 -1
- package/tiledeskChatbotPlugs/directives/Directives.js +1 -0
- package/utils/TiledeskChatbotUtil.js +2 -21
- package/TdCache copy.js +0 -242
- package/tiledeskChatbotPlugs/directives/DirWebRequestV2_old.js +0 -418
package/CHANGELOG.md
CHANGED
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
available on:
|
|
6
6
|
▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
|
|
7
7
|
|
|
8
|
-
# 2.0.9
|
|
9
|
-
|
|
10
8
|
# 2.0.9-rc1
|
|
11
9
|
- removed: speech-to-text management
|
|
12
10
|
|
|
@@ -20,6 +18,8 @@ available on:
|
|
|
20
18
|
|
|
21
19
|
# v0.5.0
|
|
22
20
|
- added: AI_ENDPOINT env var
|
|
21
|
+
|
|
22
|
+
# v0.5.0-rc1
|
|
23
23
|
- added: ability to get 'none' as bodytype in webresponse
|
|
24
24
|
|
|
25
25
|
# v0.4.2
|
|
@@ -34,6 +34,19 @@ available on:
|
|
|
34
34
|
- changed: refactoring of DIrWebRequestv2
|
|
35
35
|
- bug-fixed: erro while parsing webrequestv2 body
|
|
36
36
|
|
|
37
|
+
# v0.3.5-rc4
|
|
38
|
+
- added: webhook action (same as intent one)
|
|
39
|
+
|
|
40
|
+
# v0.3.5-rc3
|
|
41
|
+
- bug-fixed: jsonBody parse error in web-request-v2
|
|
42
|
+
|
|
43
|
+
# v0.3.5-rc2
|
|
44
|
+
- bug-fixed: cannot set status of undefined reading res.status in DirAssistant
|
|
45
|
+
|
|
46
|
+
# v0.3.5-rc1
|
|
47
|
+
- changed: refactoring web-request-v2
|
|
48
|
+
- bug-fixed: jsonBody parse error in web-request-v2
|
|
49
|
+
|
|
37
50
|
# v0.3.4
|
|
38
51
|
-bug-fixed: slit is undefined in TiledeskChatbotUtils
|
|
39
52
|
|
|
@@ -43,6 +56,18 @@ available on:
|
|
|
43
56
|
# v0.3.2
|
|
44
57
|
- bug-fixed: minor improvement
|
|
45
58
|
|
|
59
|
+
# v0.2.153-rc9
|
|
60
|
+
- changed: updated tiledesk-multi-worker to 0.2.1-rc2
|
|
61
|
+
|
|
62
|
+
# v0.2.153-rc8
|
|
63
|
+
- added: fixToken function in TiledeskService utils class
|
|
64
|
+
|
|
65
|
+
# v0.2.153-rc4
|
|
66
|
+
- log added
|
|
67
|
+
|
|
68
|
+
# v0.2.153-rc3
|
|
69
|
+
- added: specchToText function to transcript audio file
|
|
70
|
+
|
|
46
71
|
# v0.2.153-rc1
|
|
47
72
|
- changed: context for gpt-40 and gpt-40-mini
|
|
48
73
|
|
package/Logger.js
CHANGED
|
@@ -12,6 +12,8 @@ let publisher = new Publisher(AMQP_MANAGER_URL, {
|
|
|
12
12
|
exchange: "amq.topic"
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
+
console.log("LOGGER publisher: ", publisher);
|
|
16
|
+
|
|
15
17
|
class Logger {
|
|
16
18
|
|
|
17
19
|
constructor(config) {
|
|
@@ -92,6 +94,7 @@ class Logger {
|
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
let topic = LOGS_BASE_ROUTING_KEY + `.${this.request_id}`;
|
|
97
|
+
console.log("LOGGER publishing on topic ", topic)
|
|
95
98
|
publisher.publish(data, topic);
|
|
96
99
|
return;
|
|
97
100
|
}
|
package/TdCache.js
CHANGED
|
@@ -149,9 +149,23 @@ class TdCache {
|
|
|
149
149
|
})
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
async unsubscribe(topic
|
|
153
|
-
|
|
152
|
+
async unsubscribe(topic) {
|
|
153
|
+
if (!this.subscriberClient) {
|
|
154
|
+
winston.warn("Redis subscriberClient not initialized, cannot unsubscribe.");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
const result = await this.subscriberClient.unsubscribe(topic);
|
|
160
|
+
winston.debug(`Unsubscribed from topic "${topic}". Current subscription count: ${result}`);
|
|
161
|
+
} catch (err) {
|
|
162
|
+
winston.error(`Error unsubscribing from topic "${topic}":`, err);
|
|
163
|
+
}
|
|
154
164
|
}
|
|
165
|
+
|
|
166
|
+
// async unsubscribe(topic, listener) {
|
|
167
|
+
// await this.subscriberClient.unsubscribe(topic, listener);
|
|
168
|
+
// }
|
|
155
169
|
|
|
156
170
|
// subscribe(key, callback) {
|
|
157
171
|
// this.redis_sub.subscribe(key, (message) => {
|
package/index.js
CHANGED
|
@@ -13,6 +13,8 @@ const { TiledeskChatbotConst } = require('./engine/TiledeskChatbotConst.js');
|
|
|
13
13
|
const { IntentsMachineFactory } = require('./engine/IntentsMachineFactory.js');
|
|
14
14
|
const { v4: uuidv4 } = require('uuid');
|
|
15
15
|
let axios = require('axios');
|
|
16
|
+
const { customAlphabet } = require('nanoid');
|
|
17
|
+
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 10);
|
|
16
18
|
// let parser = require('accept-language-parser');
|
|
17
19
|
|
|
18
20
|
router.use(bodyParser.json({limit: '50mb'}));
|
|
@@ -98,6 +100,9 @@ router.post('/ext/:botid', async (req, res) => {
|
|
|
98
100
|
Promise.reject(err);
|
|
99
101
|
return;
|
|
100
102
|
});
|
|
103
|
+
|
|
104
|
+
winston.debug("(tybotRoute) Bot found: ", bot)
|
|
105
|
+
|
|
101
106
|
|
|
102
107
|
let intentsMachine;
|
|
103
108
|
let backupMachine;
|
|
@@ -393,6 +398,8 @@ router.post('/block/:project_id/:bot_id/:block_id', async (req, res) => {
|
|
|
393
398
|
const token = body.token;
|
|
394
399
|
delete body.async;
|
|
395
400
|
delete body.token;
|
|
401
|
+
|
|
402
|
+
let draft = req.body.draft || false;
|
|
396
403
|
|
|
397
404
|
// invoke block
|
|
398
405
|
// unique ID for each execution
|
|
@@ -402,7 +409,6 @@ router.post('/block/:project_id/:bot_id/:block_id', async (req, res) => {
|
|
|
402
409
|
} else {
|
|
403
410
|
const execution_id = uuidv4().replace(/-/g, '');
|
|
404
411
|
request_id = "automation-request-" + project_id + "-" + execution_id;
|
|
405
|
-
|
|
406
412
|
}
|
|
407
413
|
const command = "/#" + block_id;
|
|
408
414
|
let message = {
|
|
@@ -411,7 +417,8 @@ router.post('/block/:project_id/:bot_id/:block_id', async (req, res) => {
|
|
|
411
417
|
text: command,
|
|
412
418
|
id_project: project_id,
|
|
413
419
|
request: {
|
|
414
|
-
request_id: request_id
|
|
420
|
+
request_id: request_id,
|
|
421
|
+
draft: draft
|
|
415
422
|
},
|
|
416
423
|
attributes: {
|
|
417
424
|
payload: body
|
|
@@ -432,13 +439,14 @@ router.post('/block/:project_id/:bot_id/:block_id', async (req, res) => {
|
|
|
432
439
|
} else {
|
|
433
440
|
|
|
434
441
|
winston.verbose("Sync webhook. Subscribe and await for reply...")
|
|
442
|
+
let uniqueid = nanoid();
|
|
435
443
|
const topic = `/webhooks/${request_id}`;
|
|
436
444
|
|
|
437
445
|
try {
|
|
438
446
|
|
|
439
447
|
const listener = async (message, topic) => {
|
|
440
448
|
winston.debug("Web response is: " + JSON.stringify(message) + " for topic " + topic);
|
|
441
|
-
await tdcache.unsubscribe(topic
|
|
449
|
+
await tdcache.unsubscribe(topic);
|
|
442
450
|
|
|
443
451
|
let json = JSON.parse(message);
|
|
444
452
|
let status = json.status ? json.status : 200;
|
package/package.json
CHANGED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const httpUtils = require('../utils/HttpUtils');
|
|
2
|
+
const winston = require('../utils/winston');
|
|
3
|
+
const API_ENDPOINT = process.env.API_ENDPOINT;
|
|
4
|
+
|
|
5
|
+
class KbService {
|
|
6
|
+
|
|
7
|
+
constructor() { }
|
|
8
|
+
|
|
9
|
+
async getNamespace(id_project, token, name, id) {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const http_request = {
|
|
12
|
+
url: API_ENDPOINT + "/" + id_project + "/kb/namespace/all",
|
|
13
|
+
headers: {
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
'Authorization': 'JWT ' + token
|
|
16
|
+
},
|
|
17
|
+
method: "GET"
|
|
18
|
+
}
|
|
19
|
+
winston.debug("Kb HttpRequest", http_request);
|
|
20
|
+
|
|
21
|
+
httpUtils.request(
|
|
22
|
+
http_request, async (err, namespaces) => {
|
|
23
|
+
if (err) {
|
|
24
|
+
winston.error("Error getting namespaces:", err);
|
|
25
|
+
reject(err);
|
|
26
|
+
} else {
|
|
27
|
+
winston.debug("Get namespaces response:", namespaces);
|
|
28
|
+
if (!Array.isArray(namespaces)) {
|
|
29
|
+
reject(new Error('Invalid response format'));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let namespace;
|
|
34
|
+
if (name) {
|
|
35
|
+
namespace = namespaces.find(n => n.name === name);
|
|
36
|
+
} else {
|
|
37
|
+
namespace = namespaces.find(n => n.id === id);
|
|
38
|
+
}
|
|
39
|
+
resolve(namespace || null);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async getKeyFromKbSettings(id_project, token) {
|
|
47
|
+
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const http_request = {
|
|
50
|
+
url: API_ENDPOINT + "/" + id_project + "/kbsettings",
|
|
51
|
+
headers: {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
'Authorization': 'JWT ' + token
|
|
54
|
+
},
|
|
55
|
+
method: "GET"
|
|
56
|
+
}
|
|
57
|
+
winston.debug("Kb HttpRequest", http_request);
|
|
58
|
+
|
|
59
|
+
httpUtils.request(
|
|
60
|
+
http_request, async (err, resbody) => {
|
|
61
|
+
if (err) {
|
|
62
|
+
winston.error("Error getting kb settings:", err);
|
|
63
|
+
reject(err);
|
|
64
|
+
} else {
|
|
65
|
+
if (!resbody || !resbody.gptkey) {
|
|
66
|
+
resolve(null);
|
|
67
|
+
} else {
|
|
68
|
+
resolve(resbody.gptkey);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async addUnansweredQuestion(id_project, namespace, question, token) {
|
|
77
|
+
|
|
78
|
+
const json = { namespace, question };
|
|
79
|
+
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
const http_request = {
|
|
82
|
+
url: API_ENDPOINT + "/" + id_project + "/kb/unanswered/",
|
|
83
|
+
headers: {
|
|
84
|
+
'Content-Type': 'application/json',
|
|
85
|
+
'Authorization': 'JWT ' + token
|
|
86
|
+
},
|
|
87
|
+
method: "POST",
|
|
88
|
+
json: json
|
|
89
|
+
}
|
|
90
|
+
winston.debug("Kb HttpRequest", http_request);
|
|
91
|
+
|
|
92
|
+
httpUtils.request(http_request, (err, response) => {
|
|
93
|
+
if (err) {
|
|
94
|
+
winston.error("Error adding unanswered question:", err);
|
|
95
|
+
reject(err);
|
|
96
|
+
} else {
|
|
97
|
+
resolve(response);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const kbService = new KbService();
|
|
105
|
+
module.exports = kbService;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const httpUtils = require('../utils/HttpUtils');
|
|
2
|
+
const winston = require('../utils/winston');
|
|
3
|
+
const API_ENDPOINT = process.env.API_ENDPOINT;
|
|
4
|
+
|
|
5
|
+
class QuotasService {
|
|
6
|
+
|
|
7
|
+
constructor() { }
|
|
8
|
+
|
|
9
|
+
async checkQuoteAvailability(id_project, token) {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
|
|
12
|
+
const http_request = {
|
|
13
|
+
url: API_ENDPOINT + "/" + id_project + "/quotes/tokens",
|
|
14
|
+
headers: {
|
|
15
|
+
'Content-Type': 'application/json',
|
|
16
|
+
'Authorization': 'JWT ' + token
|
|
17
|
+
},
|
|
18
|
+
method: "GET"
|
|
19
|
+
}
|
|
20
|
+
winston.debug("QuotasService HttpRequest", http_request);
|
|
21
|
+
|
|
22
|
+
httpUtils.request(
|
|
23
|
+
http_request, async (err, resbody) => {
|
|
24
|
+
if (err) {
|
|
25
|
+
winston.error("Check quote availability err: ", err);
|
|
26
|
+
resolve(true)
|
|
27
|
+
} else {
|
|
28
|
+
if (resbody.isAvailable === true) {
|
|
29
|
+
resolve(true)
|
|
30
|
+
} else {
|
|
31
|
+
resolve(false)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async updateQuote(id_project, token, tokens_usage) {
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
|
|
42
|
+
const http_request = {
|
|
43
|
+
url: API_ENDPOINT + "/" + id_project + "/quotes/incr/tokens",
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
'Authorization': 'JWT ' + token
|
|
47
|
+
},
|
|
48
|
+
json: tokens_usage,
|
|
49
|
+
method: "POST"
|
|
50
|
+
}
|
|
51
|
+
winston.debug("DirAskGPTV2 update quote HttpRequest ", http_request);
|
|
52
|
+
|
|
53
|
+
httpUtils.request(
|
|
54
|
+
http_request, async (err, resbody) => {
|
|
55
|
+
if (err) {
|
|
56
|
+
winston.error("Increment tokens quote err: ", err);
|
|
57
|
+
reject(false)
|
|
58
|
+
} else {
|
|
59
|
+
resolve(true);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const quotasService = new QuotasService();
|
|
69
|
+
module.exports = quotasService;
|
|
@@ -54,13 +54,13 @@ const { DirMoveToUnassigned } = require('./directives/DirMoveToUnassigned');
|
|
|
54
54
|
const { DirAddTags } = require('./directives/DirAddTags');
|
|
55
55
|
const { DirSendWhatsapp } = require('./directives/DirSendWhatsapp');
|
|
56
56
|
const { DirReplaceBotV3 } = require('./directives/DirReplaceBotV3');
|
|
57
|
-
const {
|
|
57
|
+
const { DirAiPrompt } = require('./directives/DirAiPrompt');
|
|
58
58
|
const { DirWebResponse } = require('./directives/DirWebResponse');
|
|
59
59
|
const { DirConnectBlock } = require('./directives/DirConnectBlock');
|
|
60
|
+
const { DirAddKbContent } = require('./directives/DirAddKbContent');
|
|
61
|
+
const { DirFlowLog } = require('./directives/DirFlowLog');
|
|
60
62
|
|
|
61
63
|
const winston = require('../utils/winston');
|
|
62
|
-
const { DirFlowLog } = require('./directives/DirFlowLog');
|
|
63
|
-
const { DirAddKbContent } = require('./directives/DirAddKbContent');
|
|
64
64
|
|
|
65
65
|
class DirectivesChatbotPlug {
|
|
66
66
|
|
|
@@ -219,14 +219,13 @@ class DirectivesChatbotPlug {
|
|
|
219
219
|
directive_name = directive.name.toLowerCase();
|
|
220
220
|
}
|
|
221
221
|
if (directive && directive.action) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
222
|
+
const action_id = directive.action["_tdActionId"];
|
|
223
|
+
const locked_action_id = await this.chatbot.currentLockedAction(this.supportRequest.request_id);
|
|
224
|
+
if ( locked_action_id && (locked_action_id !== action_id) ) {
|
|
225
|
+
let next_dir = await this.nextDirective(this.directives);
|
|
226
|
+
this.process(next_dir);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
230
229
|
}
|
|
231
230
|
if (directive == null || (directive !== null && directive["name"] === undefined)) {
|
|
232
231
|
winston.debug("(DirectivesChatbotPlug) stop process(). directive is (null?): ", directive);
|
|
@@ -704,6 +703,19 @@ class DirectivesChatbotPlug {
|
|
|
704
703
|
}
|
|
705
704
|
});
|
|
706
705
|
}
|
|
706
|
+
else if (directive_name === Directives.WEBHOOK) {
|
|
707
|
+
// console.log(".....DirIntent")
|
|
708
|
+
new DirIntent(context).execute(directive, async (stop) => {
|
|
709
|
+
if (stop) {
|
|
710
|
+
if (context.log) { console.log("Stopping Actions on:", JSON.stringify(directive));}
|
|
711
|
+
this.theend();
|
|
712
|
+
}
|
|
713
|
+
else {
|
|
714
|
+
let next_dir = await this.nextDirective(this.directives);
|
|
715
|
+
this.process(next_dir);
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
}
|
|
707
719
|
else if (directive_name === Directives.WEB_RESPONSE) {
|
|
708
720
|
new DirWebResponse(context).execute(directive, async () => {
|
|
709
721
|
let next_dir = await this.nextDirective(this.directives);
|
|
@@ -716,6 +728,12 @@ class DirectivesChatbotPlug {
|
|
|
716
728
|
this.process(next_dir);
|
|
717
729
|
})
|
|
718
730
|
}
|
|
731
|
+
else if (directive_name === Directives.ADD_KB_CONTENT) {
|
|
732
|
+
new DirAddKbContent(context).execute(directive, async () => {
|
|
733
|
+
let next_dir = await this.nextDirective(this.directives);
|
|
734
|
+
this.process(next_dir);
|
|
735
|
+
});
|
|
736
|
+
}
|
|
719
737
|
else {
|
|
720
738
|
let next_dir = await this.nextDirective(this.directives);
|
|
721
739
|
this.process(next_dir);
|
|
@@ -11,6 +11,8 @@ const winston = require('../../utils/winston');
|
|
|
11
11
|
const httpUtils = require("../../utils/HttpUtils");
|
|
12
12
|
const integrationService = require("../../services/IntegrationService");
|
|
13
13
|
const { Logger } = require("../../Logger");
|
|
14
|
+
const kbService = require("../../services/KBService");
|
|
15
|
+
const quotasService = require("../../services/QuotasService");
|
|
14
16
|
|
|
15
17
|
class DirAskGPTV2 {
|
|
16
18
|
|
|
@@ -172,7 +174,7 @@ class DirAskGPTV2 {
|
|
|
172
174
|
if (!key) {
|
|
173
175
|
this.logger.native("[Ask Knowledge Base] OpenAI key not found in Integration. Using shared OpenAI key");
|
|
174
176
|
winston.verbose("DirAskGPTV2 - Key not found in Integrations. Searching in kb settings...");
|
|
175
|
-
key = await
|
|
177
|
+
key = await kbService.getKeyFromKbSettings(this.projectId, this.token);
|
|
176
178
|
}
|
|
177
179
|
|
|
178
180
|
if (!key) {
|
|
@@ -196,7 +198,7 @@ class DirAskGPTV2 {
|
|
|
196
198
|
}
|
|
197
199
|
|
|
198
200
|
if (publicKey === true && !chunks_only) {
|
|
199
|
-
let keep_going = await
|
|
201
|
+
let keep_going = await quotasService.checkQuoteAvailability(this.projectId, this.token);
|
|
200
202
|
if (keep_going === false) {
|
|
201
203
|
this.logger.warn("[Ask Knowledge Base] Tokens quota exceeded. Skip the action")
|
|
202
204
|
winston.verbose("DirAskGPTV2 - Quota exceeded for tokens. Skip the action")
|
|
@@ -340,7 +342,9 @@ class DirAskGPTV2 {
|
|
|
340
342
|
tokens: resbody.prompt_token_size,
|
|
341
343
|
model: json.model
|
|
342
344
|
}
|
|
343
|
-
|
|
345
|
+
quotasService.updateQuote(this.projectId, this.token, tokens_usage).catch((err) => {
|
|
346
|
+
winston.error("Error updating quota: ", err);
|
|
347
|
+
})
|
|
344
348
|
}
|
|
345
349
|
|
|
346
350
|
if (trueIntent) {
|
|
@@ -353,6 +357,10 @@ class DirAskGPTV2 {
|
|
|
353
357
|
}
|
|
354
358
|
} else {
|
|
355
359
|
await this.#assignAttributes(action, answer, source);
|
|
360
|
+
kbService.addUnansweredQuestion(this.projectId, json.namespace, json.question, this.token).catch((err) => {
|
|
361
|
+
winston.error("DirAskGPTV2 - Error adding unanswered question: ", err);
|
|
362
|
+
this.logger.warn("[Ask Knowledge Base] Unable to add unanswered question", json.question, "to namespacae", json.namespace);
|
|
363
|
+
})
|
|
356
364
|
if (falseIntent) {
|
|
357
365
|
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
358
366
|
callback(true);
|
|
@@ -423,93 +431,6 @@ class DirAskGPTV2 {
|
|
|
423
431
|
}
|
|
424
432
|
}
|
|
425
433
|
|
|
426
|
-
async getKeyFromKbSettings() {
|
|
427
|
-
return new Promise((resolve) => {
|
|
428
|
-
|
|
429
|
-
const KB_HTTPREQUEST = {
|
|
430
|
-
url: this.API_ENDPOINT + "/" + this.context.projectId + "/kbsettings",
|
|
431
|
-
headers: {
|
|
432
|
-
'Content-Type': 'application/json',
|
|
433
|
-
'Authorization': 'JWT ' + this.context.token
|
|
434
|
-
},
|
|
435
|
-
method: "GET"
|
|
436
|
-
}
|
|
437
|
-
winston.debug("DirAskGPTV2 KB HttpRequest", KB_HTTPREQUEST);
|
|
438
|
-
|
|
439
|
-
httpUtils.request(
|
|
440
|
-
KB_HTTPREQUEST, async (err, resbody) => {
|
|
441
|
-
if (err) {
|
|
442
|
-
winston.error("DirAskGPTV2 Get kb settings error ", err?.response?.data);
|
|
443
|
-
resolve(null);
|
|
444
|
-
} else {
|
|
445
|
-
if (!resbody.gptkey) {
|
|
446
|
-
resolve(null);
|
|
447
|
-
} else {
|
|
448
|
-
resolve(resbody.gptkey);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
)
|
|
453
|
-
})
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
async checkQuoteAvailability() {
|
|
457
|
-
return new Promise((resolve) => {
|
|
458
|
-
|
|
459
|
-
const HTTPREQUEST = {
|
|
460
|
-
url: this.API_ENDPOINT + "/" + this.context.projectId + "/quotes/tokens",
|
|
461
|
-
headers: {
|
|
462
|
-
'Content-Type': 'application/json',
|
|
463
|
-
'Authorization': 'JWT ' + this.context.token
|
|
464
|
-
},
|
|
465
|
-
method: "GET"
|
|
466
|
-
}
|
|
467
|
-
winston.debug("DirAskGPTV2 check quote availability HttpRequest", HTTPREQUEST);
|
|
468
|
-
|
|
469
|
-
httpUtils.request(
|
|
470
|
-
HTTPREQUEST, async (err, resbody) => {
|
|
471
|
-
if (err) {
|
|
472
|
-
winston.error("DirAskGPTV2 Check quote availability err: ", err);
|
|
473
|
-
resolve(true)
|
|
474
|
-
} else {
|
|
475
|
-
if (resbody.isAvailable === true) {
|
|
476
|
-
resolve(true)
|
|
477
|
-
} else {
|
|
478
|
-
resolve(false)
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
)
|
|
483
|
-
})
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
async updateQuote(tokens_usage) {
|
|
487
|
-
return new Promise((resolve, reject) => {
|
|
488
|
-
|
|
489
|
-
const HTTPREQUEST = {
|
|
490
|
-
url: this.API_ENDPOINT + "/" + this.context.projectId + "/quotes/incr/tokens",
|
|
491
|
-
headers: {
|
|
492
|
-
'Content-Type': 'application/json',
|
|
493
|
-
'Authorization': 'JWT ' + this.context.token
|
|
494
|
-
},
|
|
495
|
-
json: tokens_usage,
|
|
496
|
-
method: "POST"
|
|
497
|
-
}
|
|
498
|
-
winston.debug("DirAskGPTV2 update quote HttpRequest ", HTTPREQUEST);
|
|
499
|
-
|
|
500
|
-
httpUtils.request(
|
|
501
|
-
HTTPREQUEST, async (err, resbody) => {
|
|
502
|
-
if (err) {
|
|
503
|
-
winston.error("DirAskGPTV2 Increment tokens quote err: ", err);
|
|
504
|
-
reject(false)
|
|
505
|
-
} else {
|
|
506
|
-
resolve(true);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
)
|
|
510
|
-
})
|
|
511
|
-
}
|
|
512
|
-
|
|
513
434
|
/**
|
|
514
435
|
* Transforms the transcirpt array in a dictionary like '0': { "question": "xxx", "answer":"xxx"}
|
|
515
436
|
* merging consecutive messages with the same role in a single question or answer.
|
|
@@ -19,6 +19,8 @@ class DirReply {
|
|
|
19
19
|
this.tdcache = context.tdcache;
|
|
20
20
|
this.log = context.log;
|
|
21
21
|
this.API_ENDPOINT = context.API_ENDPOINT;
|
|
22
|
+
|
|
23
|
+
console.log("context.supportRequest: ", context.supportRequest);
|
|
22
24
|
|
|
23
25
|
this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest?.draft, intent_id: this.context.reply?.attributes?.intent_info?.intent_id });
|
|
24
26
|
this.tdClient = new TiledeskClient({ projectId: this.context.projectId, token: this.context.token, APIURL: this.API_ENDPOINT, APIKEY: "___", log: this.log });
|
|
@@ -118,7 +118,7 @@ class DirWebRequestV2 {
|
|
|
118
118
|
this.logger.native("[Web Request] resbody: ", resbody);
|
|
119
119
|
|
|
120
120
|
if (err) {
|
|
121
|
-
this.logger.error("
|
|
121
|
+
this.logger.error("[Web Request] error: ", err);
|
|
122
122
|
winston.log("webRequest error: ", err);
|
|
123
123
|
if (callback) {
|
|
124
124
|
if (falseIntent) {
|
|
@@ -58,6 +58,7 @@ class Directives {
|
|
|
58
58
|
static MOVE_TO_UNASSIGNED = "move_to_unassigned";
|
|
59
59
|
static CONNECT_BLOCK = "connect_block";
|
|
60
60
|
static ADD_TAGS = 'add_tags'
|
|
61
|
+
static WEBHOOK = 'webhook';
|
|
61
62
|
static WEB_RESPONSE = "web_response";
|
|
62
63
|
static FLOW_LOG = "flow_log";
|
|
63
64
|
static ADD_KB_CONTENT = "add_kb_content";
|
|
@@ -333,27 +333,6 @@ class TiledeskChatbotUtil {
|
|
|
333
333
|
}
|
|
334
334
|
});
|
|
335
335
|
}
|
|
336
|
-
|
|
337
|
-
// "buttons": [
|
|
338
|
-
// {
|
|
339
|
-
// "type": "action",
|
|
340
|
-
// "value": "Button1", // obbligatorio sempre
|
|
341
|
-
// "action": "#bb347206-d639-4926-94c9-e94930623dce", // mandatory
|
|
342
|
-
// "show_echo": true, // lo inserisco sempre
|
|
343
|
-
// "alias": "button1 alias"
|
|
344
|
-
// },
|
|
345
|
-
// {
|
|
346
|
-
// "type": "text",
|
|
347
|
-
// "value": "Button2 text", // obbligatorio sempre
|
|
348
|
-
// "show_echo": true // lo inserisco sempre
|
|
349
|
-
// },
|
|
350
|
-
// {
|
|
351
|
-
// "type": "url",
|
|
352
|
-
// "value": "Button3 link", // obbligatorio sempre
|
|
353
|
-
// "link": "http://", // obbligatorio
|
|
354
|
-
// "show_echo": true // lo inserisco sempre
|
|
355
|
-
// }
|
|
356
|
-
// ]
|
|
357
336
|
}
|
|
358
337
|
catch(error) {
|
|
359
338
|
winston.warn("Invalid json_buttons:", error)
|
|
@@ -604,8 +583,10 @@ class TiledeskChatbotUtil {
|
|
|
604
583
|
}
|
|
605
584
|
let currentLeadName = await chatbot.getParameter(TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY);
|
|
606
585
|
winston.debug("(TiledeskChatbotUtil) You lead email from attributes: " + currentLeadEmail);
|
|
586
|
+
console.log("currentLeadName: ", currentLeadName)
|
|
607
587
|
if (message.request.lead.fullname && !currentLeadName) {
|
|
608
588
|
// worth saving
|
|
589
|
+
console.log("inside if")
|
|
609
590
|
winston.debug("(TiledeskChatbotUtil) worth saving email");
|
|
610
591
|
try {
|
|
611
592
|
await chatbot.addParameter(TiledeskChatbotConst.REQ_LEAD_USERFULLNAME_KEY, message.request.lead.fullname);
|
package/TdCache copy.js
DELETED
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
const redis = require('redis');
|
|
2
|
-
|
|
3
|
-
class TdCache {
|
|
4
|
-
|
|
5
|
-
constructor(config) {
|
|
6
|
-
this.redis_host = config.host;
|
|
7
|
-
this.redis_port = config.port;
|
|
8
|
-
this.redis_password = config.password;
|
|
9
|
-
this.client = null;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async connect(callback) {
|
|
13
|
-
// client = redis.createClient();
|
|
14
|
-
return new Promise( async (resolve, reject) => {
|
|
15
|
-
this.client = redis.createClient(
|
|
16
|
-
{
|
|
17
|
-
host: this.redis_host,
|
|
18
|
-
port: this.redis_port,
|
|
19
|
-
password: this.redis_password
|
|
20
|
-
});
|
|
21
|
-
this.client.on('error', err => {
|
|
22
|
-
reject(err);
|
|
23
|
-
if (callback) {
|
|
24
|
-
callback(err);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
// this.client.on('connect', function() {
|
|
28
|
-
// console.log('Redis Connected!');
|
|
29
|
-
// });
|
|
30
|
-
this.client.on('ready',function() {
|
|
31
|
-
console.log("connected")
|
|
32
|
-
resolve();
|
|
33
|
-
if (callback) {
|
|
34
|
-
callback();
|
|
35
|
-
}
|
|
36
|
-
//console.log("Redis is ready.");
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async set(key, value, options) {
|
|
42
|
-
//console.log("setting key value", key, value)
|
|
43
|
-
if (!options) {
|
|
44
|
-
options = {EX: 86400}
|
|
45
|
-
}
|
|
46
|
-
return new Promise( async (resolve, reject) => {
|
|
47
|
-
if (options && options.EX) {
|
|
48
|
-
//console.log("expires:", options.EX)
|
|
49
|
-
try {
|
|
50
|
-
await this.client.set(
|
|
51
|
-
key,
|
|
52
|
-
value,
|
|
53
|
-
'EX', options.EX);
|
|
54
|
-
}
|
|
55
|
-
catch(error) {
|
|
56
|
-
reject(error)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
try {
|
|
61
|
-
//console.log("setting here...key", key, value)
|
|
62
|
-
await this.client.set(
|
|
63
|
-
key,
|
|
64
|
-
value);
|
|
65
|
-
}
|
|
66
|
-
catch(error) {
|
|
67
|
-
console.error("Error", error);
|
|
68
|
-
reject(error)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (options && options.callback) {
|
|
72
|
-
options.callback();
|
|
73
|
-
}
|
|
74
|
-
//console.log("resolving...", key);
|
|
75
|
-
return resolve();
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async incr(key) {
|
|
80
|
-
// console.log("incr key:", key)
|
|
81
|
-
return new Promise( async (resolve, reject) => {
|
|
82
|
-
try {
|
|
83
|
-
// console.log("incr here...key", key)
|
|
84
|
-
await this.client.incr(key);
|
|
85
|
-
}
|
|
86
|
-
catch(error) {
|
|
87
|
-
console.error("Error on incr:", error);
|
|
88
|
-
reject(error)
|
|
89
|
-
}
|
|
90
|
-
return resolve();
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async hset(dict_key, key, value, options) {
|
|
95
|
-
//console.log("hsetting dict_key key value", dict_key, key, value)
|
|
96
|
-
return new Promise( async (resolve, reject) => {
|
|
97
|
-
if (options && options.EX) {
|
|
98
|
-
//console.log("expires:", options.EX)
|
|
99
|
-
try {
|
|
100
|
-
await this.client.hset(
|
|
101
|
-
dict_key,
|
|
102
|
-
key,
|
|
103
|
-
value,
|
|
104
|
-
'EX', options.EX);
|
|
105
|
-
}
|
|
106
|
-
catch(error) {
|
|
107
|
-
reject(error)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
try {
|
|
112
|
-
//console.log("setting here...key", key, value)
|
|
113
|
-
await this.client.hset(
|
|
114
|
-
dict_key,
|
|
115
|
-
key,
|
|
116
|
-
value);
|
|
117
|
-
}
|
|
118
|
-
catch(error) {
|
|
119
|
-
console.error("Error", error);
|
|
120
|
-
reject(error)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (options && options.callback) {
|
|
124
|
-
options.callback();
|
|
125
|
-
}
|
|
126
|
-
return resolve();
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async hdel(dict_key, key, options) {
|
|
131
|
-
//console.log("hsetting dict_key key value", dict_key, key, value)
|
|
132
|
-
return new Promise( async (resolve, reject) => {
|
|
133
|
-
if (options && options.EX) {
|
|
134
|
-
//console.log("expires:", options.EX)
|
|
135
|
-
try {
|
|
136
|
-
await this.client.hdel(
|
|
137
|
-
dict_key,
|
|
138
|
-
key,
|
|
139
|
-
'EX', options.EX);
|
|
140
|
-
}
|
|
141
|
-
catch(error) {
|
|
142
|
-
reject(error)
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
try {
|
|
147
|
-
//console.log("setting here...key", key, value)
|
|
148
|
-
await this.client.hdel(
|
|
149
|
-
dict_key,
|
|
150
|
-
key);
|
|
151
|
-
}
|
|
152
|
-
catch(error) {
|
|
153
|
-
console.error("Error", error);
|
|
154
|
-
reject(error);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
if (options && options.callback) {
|
|
158
|
-
options.callback();
|
|
159
|
-
}
|
|
160
|
-
return resolve();
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async setJSON(key, value, options) {
|
|
165
|
-
const _string = JSON.stringify(value);
|
|
166
|
-
return await this.set(key, _string, options);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async get(key, callback) {
|
|
170
|
-
//console.log("getting key", key)
|
|
171
|
-
return new Promise( async (resolve, reject) => {
|
|
172
|
-
this.client.get(key, (err, value) => {
|
|
173
|
-
if (err) {
|
|
174
|
-
reject(err);
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
if (callback) {
|
|
178
|
-
callback(value);
|
|
179
|
-
}
|
|
180
|
-
return resolve(value);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async hgetall(dict_key, callback) {
|
|
187
|
-
//console.log("hgetting dics", dict_key);
|
|
188
|
-
return new Promise( async (resolve, reject) => {
|
|
189
|
-
this.client.hgetall(dict_key, (err, value) => {
|
|
190
|
-
if (err) {
|
|
191
|
-
reject(err);
|
|
192
|
-
if (callback) {
|
|
193
|
-
callback(err, null);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
if (callback) {
|
|
198
|
-
callback(null, value);
|
|
199
|
-
}
|
|
200
|
-
resolve(value);
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
async hget(dict_key, key, callback) {
|
|
207
|
-
//console.log("hgetting dics", dict_key);
|
|
208
|
-
return new Promise( async (resolve, reject) => {
|
|
209
|
-
this.client.hget(dict_key, key, (err, value) => {
|
|
210
|
-
if (err) {
|
|
211
|
-
reject(err);
|
|
212
|
-
if (callback) {
|
|
213
|
-
callback(err, null);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
if (callback) {
|
|
218
|
-
callback(null, value);
|
|
219
|
-
}
|
|
220
|
-
resolve(value);
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
async getJSON(key, callback) {
|
|
227
|
-
const value = await this.get(key);
|
|
228
|
-
return JSON.parse(value);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
async del(key, callback) {
|
|
232
|
-
return new Promise( async (resolve, reject) => {
|
|
233
|
-
await this.client.del(key);
|
|
234
|
-
if (callback) {
|
|
235
|
-
callback();
|
|
236
|
-
}
|
|
237
|
-
return resolve();
|
|
238
|
-
})
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
module.exports = { TdCache };
|
|
@@ -1,418 +0,0 @@
|
|
|
1
|
-
let axios = require('axios');
|
|
2
|
-
let https = require("https");
|
|
3
|
-
const { Filler } = require('../Filler');
|
|
4
|
-
const { TiledeskChatbot } = require('../../engine/TiledeskChatbot');
|
|
5
|
-
const { DirIntent } = require('./DirIntent');
|
|
6
|
-
|
|
7
|
-
class DirWebRequestV2 {
|
|
8
|
-
constructor(context) {
|
|
9
|
-
if (!context) {
|
|
10
|
-
throw new Error('context object is mandatory.');
|
|
11
|
-
}
|
|
12
|
-
this.context = context;
|
|
13
|
-
this.tdcache = context.tdcache;
|
|
14
|
-
this.requestId = context.requestId;
|
|
15
|
-
this.chatbot = context.chatbot;
|
|
16
|
-
this.log = context.log;
|
|
17
|
-
|
|
18
|
-
this.intentDir = new DirIntent(context);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
execute(directive, callback) {
|
|
22
|
-
let action;
|
|
23
|
-
if (directive.action) {
|
|
24
|
-
action = directive.action;
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
console.error("Incorrect directive:", JSON.stringify(directive));
|
|
28
|
-
callback();
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
this.go(action, (stop) => {
|
|
32
|
-
if (this.log) {console.log("(webrequestv2, stop?", stop); }
|
|
33
|
-
callback(stop);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async go(action, callback) {
|
|
38
|
-
if (this.log) {console.log("webRequest action:", JSON.stringify(action));}
|
|
39
|
-
|
|
40
|
-
// Condition branches
|
|
41
|
-
let trueIntent = action.trueIntent;
|
|
42
|
-
let falseIntent = action.falseIntent;
|
|
43
|
-
const trueIntentAttributes = action.trueIntentAttributes;
|
|
44
|
-
const falseIntentAttributes = action.falseIntentAttributes;
|
|
45
|
-
let stopOnConditionMet = action.stopOnConditionMet;
|
|
46
|
-
if (trueIntent && trueIntent.trim() === "") {
|
|
47
|
-
trueIntent = null;
|
|
48
|
-
}
|
|
49
|
-
if (falseIntent && falseIntent.trim() === "") {
|
|
50
|
-
falseIntent = null;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let requestAttributes = null;
|
|
54
|
-
if (this.tdcache) {
|
|
55
|
-
requestAttributes =
|
|
56
|
-
await TiledeskChatbot.allParametersStatic(
|
|
57
|
-
this.tdcache, this.requestId
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
const filler = new Filler();
|
|
61
|
-
const url = filler.fill(action.url, requestAttributes);
|
|
62
|
-
|
|
63
|
-
let headers = {};
|
|
64
|
-
if (action.headersString) {
|
|
65
|
-
let headersDict = action.headersString
|
|
66
|
-
for (const [key, value] of Object.entries(headersDict)) {
|
|
67
|
-
if (this.log) {console.log("header:", key, "value:", value)}
|
|
68
|
-
let filled_value = filler.fill(value, requestAttributes);
|
|
69
|
-
headers[key] = filled_value;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
let json = null;
|
|
74
|
-
try {
|
|
75
|
-
if (action.jsonBody && action.bodyType == "json") {
|
|
76
|
-
if (this.log) {console.log("action.body is:", action.jsonBody);}
|
|
77
|
-
let jsonBody = filler.fill(action.jsonBody, requestAttributes);
|
|
78
|
-
try {
|
|
79
|
-
json = JSON.parse(jsonBody);
|
|
80
|
-
if (this.log) {console.log("json is:", json);}
|
|
81
|
-
}
|
|
82
|
-
catch(err) {
|
|
83
|
-
console.error("Error parsing webRequest jsonBody:", jsonBody);
|
|
84
|
-
if (callback) {
|
|
85
|
-
if (falseIntent) {
|
|
86
|
-
await this.chatbot.addParameter("flowError", "Error parsing jsonBody");
|
|
87
|
-
this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, () => {
|
|
88
|
-
console.log('herrrrr 11111' )
|
|
89
|
-
callback(true); // stop the flow
|
|
90
|
-
return;
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
console.log('herrrrr 2222' )
|
|
95
|
-
callback(false); // continue the flow
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
else if (action.formData && action.bodyType == "form-data") {
|
|
102
|
-
let formData = filler.fill(action.formData, requestAttributes);
|
|
103
|
-
if (this.log) {console.log("action.body is form-data:", formData);}
|
|
104
|
-
// // fill
|
|
105
|
-
if (formData && formData.length > 0) {
|
|
106
|
-
for (let i = 0; i < formData.length; i++) {
|
|
107
|
-
let field = formData[i];
|
|
108
|
-
if (field.value) {
|
|
109
|
-
field.value = filler.fill(field.value, requestAttributes);
|
|
110
|
-
if (this.log) {console.log("field filled:", field.value);}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
json = {};
|
|
115
|
-
for (let i = 0; i < formData.length; i++) {
|
|
116
|
-
let field = formData[i];
|
|
117
|
-
if (field.enabled && field.value && field.type === "URL") {
|
|
118
|
-
if (this.log) {console.log("Getting file:", field.value);}
|
|
119
|
-
let response = await axios.get(field.value,
|
|
120
|
-
{
|
|
121
|
-
responseType: 'stream'
|
|
122
|
-
}
|
|
123
|
-
);
|
|
124
|
-
let stream = response.data;
|
|
125
|
-
// if (this.log) {console.log("Stream data:", stream);}
|
|
126
|
-
json[field.name] = stream;
|
|
127
|
-
// process.exit(0);
|
|
128
|
-
}
|
|
129
|
-
else if (field.enabled && field.value && field.type === "Text") {
|
|
130
|
-
json[field.name] = field.value;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (this.log) {console.log("final json:", json);}
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
if (this.log) {console.log("no action upload parts");}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
catch(error) {
|
|
141
|
-
console.error("Error", error);
|
|
142
|
-
if (callback) {
|
|
143
|
-
if (falseIntent) {
|
|
144
|
-
await this.chatbot.addParameter("flowError", "Error: " + error);
|
|
145
|
-
this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, () => {
|
|
146
|
-
callback(true); // stop the flow
|
|
147
|
-
return;
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
callback(false); // continue the flow
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
let timeout = this.#webrequest_timeout(action, 20000, 1, 300000);
|
|
160
|
-
|
|
161
|
-
if (this.log) {console.log("webRequest URL", url);}
|
|
162
|
-
|
|
163
|
-
const HTTPREQUEST = {
|
|
164
|
-
url: url,
|
|
165
|
-
headers: headers,
|
|
166
|
-
json: json,
|
|
167
|
-
method: action.method,
|
|
168
|
-
timeout: timeout
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
if (this.log) {console.log("webRequest HTTPREQUEST", HTTPREQUEST);}
|
|
172
|
-
this.#myrequest(
|
|
173
|
-
HTTPREQUEST, async (err, res) => {
|
|
174
|
-
if (this.log && err) {
|
|
175
|
-
console.log("webRequest error:", err);
|
|
176
|
-
}
|
|
177
|
-
if (this.log) {console.log("got res:", res);}
|
|
178
|
-
let resbody = res.data;
|
|
179
|
-
let status = res.status;
|
|
180
|
-
let error = res.error;
|
|
181
|
-
await this.#assignAttributes(action, resbody, status, error)
|
|
182
|
-
if (this.log) {console.log("webRequest resbody:", resbody);}
|
|
183
|
-
if (err) {
|
|
184
|
-
if (this.log) {console.error("webRequest error:", err);}
|
|
185
|
-
if (callback) {
|
|
186
|
-
if (falseIntent) {
|
|
187
|
-
this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, () => {
|
|
188
|
-
callback(true); // stop the flow
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
callback(false); // continue the flow
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
else if(res.status >= 200 && res.status <= 299) {
|
|
197
|
-
if (trueIntent) {
|
|
198
|
-
await this.#executeCondition(true, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, () => {
|
|
199
|
-
callback(true); // stop the flow
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
else {
|
|
203
|
-
callback(false); // continue the flow
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
if (falseIntent) {
|
|
208
|
-
this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, () => {
|
|
209
|
-
callback(true); // stop the flow
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
callback(false); // continue the flow
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
async #executeCondition(result, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, callback) {
|
|
221
|
-
let trueIntentDirective = null;
|
|
222
|
-
if (trueIntent) {
|
|
223
|
-
trueIntentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
|
|
224
|
-
}
|
|
225
|
-
let falseIntentDirective = null;
|
|
226
|
-
if (falseIntent) {
|
|
227
|
-
falseIntentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
|
|
228
|
-
}
|
|
229
|
-
if (result === true) {
|
|
230
|
-
if (trueIntentDirective) {
|
|
231
|
-
this.intentDir.execute(trueIntentDirective, () => {
|
|
232
|
-
callback();
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
if (this.log) {console.log("No trueIntentDirective specified");}
|
|
237
|
-
callback();
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
if (falseIntentDirective) {
|
|
242
|
-
this.intentDir.execute(falseIntentDirective, () => {
|
|
243
|
-
callback();
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
if (this.log) {console.log("No falseIntentDirective specified");}
|
|
248
|
-
callback();
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
async #assignAttributes(action, resbody, status, error) {
|
|
254
|
-
if (this.log) {
|
|
255
|
-
console.log("assignAttributes resbody:", resbody)
|
|
256
|
-
console.log("assignAttributes error:", error)
|
|
257
|
-
console.log("assignAttributes status:", status)
|
|
258
|
-
console.log("assignAttributes action:", action)
|
|
259
|
-
}
|
|
260
|
-
if (this.context.tdcache) {
|
|
261
|
-
if (action.assignResultTo && resbody) {
|
|
262
|
-
if (this.log) {console.log("assign assignResultTo:", resbody);}
|
|
263
|
-
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignResultTo, resbody);
|
|
264
|
-
}
|
|
265
|
-
if (action.assignErrorTo && error) {
|
|
266
|
-
if (this.log) {console.log("assign assignResultTo:", error);}
|
|
267
|
-
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignErrorTo, error);
|
|
268
|
-
}
|
|
269
|
-
if (action.assignStatusTo && status) {
|
|
270
|
-
if (this.log) {console.log("assign assignStatusTo:", status);}
|
|
271
|
-
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignStatusTo, status);
|
|
272
|
-
}
|
|
273
|
-
// Debug log
|
|
274
|
-
if (this.log) {
|
|
275
|
-
const all_parameters = await TiledeskChatbot.allParametersStatic(this.context.tdcache, this.context.requestId);
|
|
276
|
-
for (const [key, value] of Object.entries(all_parameters)) {
|
|
277
|
-
if (this.log) {console.log("(webRequest) request parameter:", key, "value:", value, "type:", typeof value)}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
#myrequest(options, callback) {
|
|
284
|
-
try {
|
|
285
|
-
if (this.log) {
|
|
286
|
-
console.log("API URL:", options.url);
|
|
287
|
-
//console.log("** Options:", JSON.stringify(options));
|
|
288
|
-
// Stringify "options". FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - START
|
|
289
|
-
let cache = [];
|
|
290
|
-
let str_Options = JSON.stringify(options, function(key, value) { // try to use a separate function
|
|
291
|
-
if (typeof value === 'object' && value != null) {
|
|
292
|
-
if (cache.indexOf(value) !== -1) {
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
cache.push(value);
|
|
296
|
-
}
|
|
297
|
-
return value;
|
|
298
|
-
});
|
|
299
|
-
console.log("** Options:", str_Options);
|
|
300
|
-
}
|
|
301
|
-
let axios_options = {
|
|
302
|
-
url: options.url,
|
|
303
|
-
method: options.method,
|
|
304
|
-
params: options.params,
|
|
305
|
-
headers: options.headers,
|
|
306
|
-
timeout: options.timeout,
|
|
307
|
-
maxContentLength: 10000000, // max 10mb response size
|
|
308
|
-
maxBodyLength: 10000000 // max 10mb request body size
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (options.json !== null) {
|
|
312
|
-
axios_options.data = options.json
|
|
313
|
-
}
|
|
314
|
-
// if (this.log) {
|
|
315
|
-
// console.log("axios_options:", JSON.stringify(axios_options));
|
|
316
|
-
// }
|
|
317
|
-
if (options.url.startsWith("https:")) {
|
|
318
|
-
const httpsAgent = new https.Agent({
|
|
319
|
-
rejectUnauthorized: false,
|
|
320
|
-
});
|
|
321
|
-
axios_options.httpsAgent = httpsAgent;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
axios(axios_options)
|
|
325
|
-
.then((res) => {
|
|
326
|
-
if (this.log) {
|
|
327
|
-
console.log("Success Response:", res);
|
|
328
|
-
console.log("Response for url:", options.url);
|
|
329
|
-
console.log("Response headers:\n", JSON.stringify(res.headers));
|
|
330
|
-
}
|
|
331
|
-
if (callback) {
|
|
332
|
-
callback(null, res);
|
|
333
|
-
}
|
|
334
|
-
})
|
|
335
|
-
.catch( (err) => {
|
|
336
|
-
if (this.log) {
|
|
337
|
-
if (err.response) {
|
|
338
|
-
console.log("Error Response data:", err.response.data);
|
|
339
|
-
}
|
|
340
|
-
// FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - START
|
|
341
|
-
let cache = [];
|
|
342
|
-
let error_log = JSON.stringify(err, function(key, value) { // try to use a separate function
|
|
343
|
-
if (typeof value === 'object' && value != null) {
|
|
344
|
-
if (cache.indexOf(value) !== -1) {
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
cache.push(value);
|
|
348
|
-
}
|
|
349
|
-
return value;
|
|
350
|
-
});
|
|
351
|
-
console.error("An error occurred: ", error_log);
|
|
352
|
-
// FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - END
|
|
353
|
-
// console.error("An error occurred:", JSON.stringify(err));
|
|
354
|
-
}
|
|
355
|
-
if (callback) {
|
|
356
|
-
let status = 1000;
|
|
357
|
-
let cache = [];
|
|
358
|
-
let str_error = JSON.stringify(err, function(key, value) { // try to use a separate function
|
|
359
|
-
if (typeof value === 'object' && value != null) {
|
|
360
|
-
if (cache.indexOf(value) !== -1) {
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
cache.push(value);
|
|
364
|
-
}
|
|
365
|
-
return value;
|
|
366
|
-
});
|
|
367
|
-
let error = JSON.parse(str_error) // "status" disappears without this trick
|
|
368
|
-
let errorMessage = JSON.stringify(error);
|
|
369
|
-
if (error.status) {
|
|
370
|
-
status = error.status;
|
|
371
|
-
}
|
|
372
|
-
if (error.message) {
|
|
373
|
-
errorMessage = error.message;
|
|
374
|
-
}
|
|
375
|
-
let data = null;
|
|
376
|
-
if (err.response) {
|
|
377
|
-
data = err.response.data;
|
|
378
|
-
}
|
|
379
|
-
callback(
|
|
380
|
-
null, {
|
|
381
|
-
status: status,
|
|
382
|
-
data: data,
|
|
383
|
-
error: errorMessage
|
|
384
|
-
}
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
catch(error) {
|
|
390
|
-
console.error("Error:", error);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
#webrequest_timeout(action, default_timeout, min, max) {
|
|
395
|
-
let timeout = default_timeout;
|
|
396
|
-
if (!action.settings) {
|
|
397
|
-
return timeout;
|
|
398
|
-
}
|
|
399
|
-
// console.log("default timeout:", timeout);
|
|
400
|
-
// console.log("action.settings:", action.settings);
|
|
401
|
-
// console.log("action.settings.timeout:", action.settings.timeout);
|
|
402
|
-
// console.log("typeof action.settings.timeout:", typeof action.settings.timeout);
|
|
403
|
-
// console.log("action.settings.timeout > min", action.settings.timeout > min)
|
|
404
|
-
// console.log("action.settings.timeout < max", action.settings.timeout < max)
|
|
405
|
-
|
|
406
|
-
if (action.settings.timeout) {
|
|
407
|
-
if ((typeof action.settings.timeout === "number") && action.settings.timeout > min && action.settings.timeout < max) {
|
|
408
|
-
timeout = Math.round(action.settings.timeout)
|
|
409
|
-
// console.log("new timeout:", timeout);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
// console.log("returning timeout:", timeout);
|
|
413
|
-
return timeout
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
module.exports = { DirWebRequestV2 };
|