@tiledesk/tiledesk-tybot-connector 0.1.96 → 0.1.98
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 +7 -1
- package/TdCache.js +3 -0
- package/index.js +28 -17
- package/models/IntentForm.js +8 -6
- package/models/TiledeskChatbot.js +49 -2
- package/package.json +1 -1
- package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +52 -4
- package/tiledeskChatbotPlugs/directives/DirAskGPT.js +2 -1
- package/tiledeskChatbotPlugs/directives/DirCaptureUserReply.js +128 -0
- package/tiledeskChatbotPlugs/directives/DirDepartment.js +62 -11
- package/tiledeskChatbotPlugs/directives/DirForm.js +90 -36
- package/tiledeskChatbotPlugs/directives/DirJSONCondition.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirMessage.js +2 -1
- package/tiledeskChatbotPlugs/directives/DirReply.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirWebRequestV2.js +26 -2
- package/tiledeskChatbotPlugs/directives/DirWhatsappByAttribute.js +2 -1
- package/tiledeskChatbotPlugs/directives/Directives.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,11 +5,17 @@
|
|
|
5
5
|
available on:
|
|
6
6
|
▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
|
|
7
7
|
|
|
8
|
+
### 0.1.98 - online
|
|
9
|
+
- added default EX:86400 to exprire time to tdcache.set()
|
|
10
|
+
- added "chatbot" instance to DirectivesChatbotPlug instance created in index.js
|
|
11
|
+
- added Capture user Reply
|
|
12
|
+
- added triggerBot to DirDepartment
|
|
13
|
+
|
|
8
14
|
### 0.1.96 - online
|
|
9
15
|
|
|
10
16
|
### 0.1.95
|
|
11
|
-
- added "chatbot" instance to DirectivesChatbotPlug instance created in index.js
|
|
12
17
|
- Fix: missing key API_ENDPOINT in production
|
|
18
|
+
- added "message: message" to DirectivesChatbotPlug instance created in index.js
|
|
13
19
|
|
|
14
20
|
### 0.1.94
|
|
15
21
|
- Fix: last_user_message on _tdInternal sender
|
package/TdCache.js
CHANGED
|
@@ -39,6 +39,9 @@ class TdCache {
|
|
|
39
39
|
|
|
40
40
|
async set(key, value, options) {
|
|
41
41
|
//console.log("setting key value", key, value)
|
|
42
|
+
if (!options) {
|
|
43
|
+
options = {EX: 86400}
|
|
44
|
+
}
|
|
42
45
|
return new Promise( async (resolve, reject) => {
|
|
43
46
|
if (options && options.EX) {
|
|
44
47
|
//console.log("expires:", options.EX)
|
package/index.js
CHANGED
|
@@ -151,27 +151,38 @@ router.post('/ext/:botid', async (req, res) => {
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
// console.log("reply is:", reply);
|
|
154
|
+
// if (reply.attributes.intent_info.intent_id) {
|
|
155
|
+
// process.exit(1)
|
|
156
|
+
// }
|
|
154
157
|
if (reply.actions && reply.actions.length > 0) { // structured actions (coming from chatbot designer)
|
|
155
158
|
if (log) {console.log("the actions:", JSON.stringify(reply.actions));}
|
|
156
159
|
let directives = actionsToDirectives(reply.actions);
|
|
157
160
|
if (log) {console.log("the directives:", JSON.stringify(directives));}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
161
|
+
try {
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
let directivesPlug = new DirectivesChatbotPlug(
|
|
165
|
+
{
|
|
166
|
+
message: message,
|
|
167
|
+
reply: reply,
|
|
168
|
+
directives: directives,
|
|
169
|
+
chatbot: chatbot,
|
|
170
|
+
supportRequest: message.request,
|
|
171
|
+
TILEDESK_API_ENDPOINT: APIURL,
|
|
172
|
+
TILEBOT_ENDPOINT:process.env.TYBOT_ENDPOINT,
|
|
173
|
+
token: token,
|
|
174
|
+
log: log,
|
|
175
|
+
HELP_CENTER_API_ENDPOINT: process.env.HELP_CENTER_API_ENDPOINT,
|
|
176
|
+
cache: tdcache
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
directivesPlug.processDirectives( () => {
|
|
180
|
+
if (log) {console.log("Actions - Directives executed.");}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
console.error("an error:", error);
|
|
185
|
+
}
|
|
175
186
|
}
|
|
176
187
|
else { // text answer (parse text directives to get actions)
|
|
177
188
|
if (log) {console.log("an answer:", reply.text);}
|
package/models/IntentForm.js
CHANGED
|
@@ -62,7 +62,14 @@ class IntentForm {
|
|
|
62
62
|
*/
|
|
63
63
|
async getMessage(user_text) {
|
|
64
64
|
//console.log("get message:", user_text)
|
|
65
|
+
let current_form = null;
|
|
66
|
+
const _current_form = await this.getValue(this.CURRENT_FORM_KEY);
|
|
67
|
+
if (_current_form) {
|
|
68
|
+
current_form = JSON.parse(_current_form);
|
|
69
|
+
}
|
|
70
|
+
//console.log("CURRENT FORM IS", current_form);
|
|
65
71
|
if (
|
|
72
|
+
current_form &&
|
|
66
73
|
this.form &&
|
|
67
74
|
this.form.cancelCommands &&
|
|
68
75
|
this.form.cancelCommands.includes(user_text.toLowerCase())) {
|
|
@@ -81,12 +88,7 @@ class IntentForm {
|
|
|
81
88
|
if (_current_field) {
|
|
82
89
|
current_field = Number(_current_field);
|
|
83
90
|
}
|
|
84
|
-
|
|
85
|
-
const _current_form = await this.getValue(this.CURRENT_FORM_KEY);
|
|
86
|
-
if (_current_form) {
|
|
87
|
-
current_form = JSON.parse(_current_form);
|
|
88
|
-
}
|
|
89
|
-
//console.log("CURRENT FORM IS", current_form);
|
|
91
|
+
|
|
90
92
|
if (current_field == null) {
|
|
91
93
|
if (this.log) {console.log("current_field is undefined")}
|
|
92
94
|
current_field = 0;
|
|
@@ -63,6 +63,30 @@ class TiledeskChatbot {
|
|
|
63
63
|
console.log("replyToMessage() > lead found:", JSON.stringify(lead));
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// reset lockedIntent on direct user invocation ( /intent or action => this only?)
|
|
67
|
+
if (message.sender != "_tdinternal") {
|
|
68
|
+
try {
|
|
69
|
+
// if (this.log) {console.log("Checking locked intent reset on explicit intent invokation.");}
|
|
70
|
+
// if (message.text.startsWith("/")) {
|
|
71
|
+
// if (this.log) {console.log("RESETTING LOCKED INTENT. Intent was explicitly invoked with / command...", message.text);}
|
|
72
|
+
// await this.unlockIntent(this.requestId);
|
|
73
|
+
// await this.unlockAction(this.requestId);
|
|
74
|
+
// if (this.log) {console.log("RESET LOCKED INTENT. Intent was explicitly invoked with / command:", message.text);}
|
|
75
|
+
// }
|
|
76
|
+
if (this.log) {console.log("Checking locked intent reset on action invocation.");}
|
|
77
|
+
if (message.attributes && message.attributes.action) {
|
|
78
|
+
if (this.log) {console.log("Message has action:", message.attributes.action)}
|
|
79
|
+
if (this.log) {console.log("RESETTING LOCKED INTENT. Intent was explicitly invoked with an action:", message.attributes.action);}
|
|
80
|
+
await this.unlockIntent(this.requestId);
|
|
81
|
+
await this.unlockAction(this.requestId);
|
|
82
|
+
if (this.log) {console.log("RESET LOCKED INTENT. Intent was explicitly invoked with an action:", message.attributes.action);}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch(error) {
|
|
86
|
+
console.error("Error resetting locked intent:", error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
66
90
|
// any external invocation restarts the steps counter
|
|
67
91
|
if (message.sender != "_tdinternal") {
|
|
68
92
|
if (this.log) {
|
|
@@ -475,6 +499,7 @@ class TiledeskChatbot {
|
|
|
475
499
|
delete question_payload.request;
|
|
476
500
|
const intent_info = {
|
|
477
501
|
intent_name: answerObj.intent_display_name,
|
|
502
|
+
intent_id: answerObj.intent_id,
|
|
478
503
|
is_fallback: false,
|
|
479
504
|
confidence: answerObj.score,
|
|
480
505
|
question_payload: question_payload,
|
|
@@ -500,8 +525,8 @@ class TiledeskChatbot {
|
|
|
500
525
|
return bot_answer;
|
|
501
526
|
}
|
|
502
527
|
|
|
528
|
+
|
|
503
529
|
async lockIntent(requestId, intent_name) {
|
|
504
|
-
// await this.tdcache.set("tilebot:requests:" + requestId + ":locked", intent_name);
|
|
505
530
|
await DirLockIntent.lockIntent(this.tdcache, requestId, intent_name);
|
|
506
531
|
}
|
|
507
532
|
|
|
@@ -516,7 +541,29 @@ class TiledeskChatbot {
|
|
|
516
541
|
|
|
517
542
|
async unlockIntent(requestId) {
|
|
518
543
|
await DirUnlockIntent.unlockIntent(this.tdcache, requestId);
|
|
519
|
-
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
async lockAction(requestId, action_id) {
|
|
547
|
+
if (this.tdcache != null && requestId != null && action_id != null) {
|
|
548
|
+
await this.tdcache.set("tilebot:requests:" + requestId + ":action:locked", action_id);
|
|
549
|
+
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
console.error("lockAction recoverable error, one of requestId:", requestId, "action_id:", action_id, "is null");
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
async currentLockedAction(requestId) {
|
|
557
|
+
if (this.tdcache) {
|
|
558
|
+
return await this.tdcache.get("tilebot:requests:" + requestId + ":action:locked");
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
async unlockAction(requestId) {
|
|
566
|
+
await this.tdcache.del("tilebot:requests:" + requestId + ":action:locked");
|
|
520
567
|
}
|
|
521
568
|
|
|
522
569
|
async addParameter(parameter_name, parameter_value) {
|
package/package.json
CHANGED
|
@@ -36,6 +36,8 @@ const { DirIfOnlineAgents } = require('./directives/DirIfOnlineAgents');
|
|
|
36
36
|
const { DirReply } = require('./directives/DirReply');
|
|
37
37
|
const { DirRandomReply } = require('./directives/DirRandomReply');
|
|
38
38
|
const { DirGptTask } = require('./directives/DirGptTask');
|
|
39
|
+
const { DirForm } = require('./directives/DirForm');
|
|
40
|
+
const { DirCaptureUserReply } = require('./directives/DirCaptureUserReply');
|
|
39
41
|
|
|
40
42
|
class DirectivesChatbotPlug {
|
|
41
43
|
|
|
@@ -56,6 +58,7 @@ class DirectivesChatbotPlug {
|
|
|
56
58
|
this.directives = config.directives;
|
|
57
59
|
this.reply = config.reply;
|
|
58
60
|
this.chatbot = config.chatbot;
|
|
61
|
+
this.message = config.message;
|
|
59
62
|
// console.log("We have the support request:", JSON.stringify(this.supportRequest))
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -103,7 +106,7 @@ class DirectivesChatbotPlug {
|
|
|
103
106
|
return;
|
|
104
107
|
}
|
|
105
108
|
const supportRequest = this.supportRequest;
|
|
106
|
-
|
|
109
|
+
console.log("supportRequest is:", JSON.stringify(supportRequest))
|
|
107
110
|
|
|
108
111
|
const token = this.token;
|
|
109
112
|
const API_URL = this.API_URL;
|
|
@@ -128,6 +131,8 @@ class DirectivesChatbotPlug {
|
|
|
128
131
|
|
|
129
132
|
this.context = {
|
|
130
133
|
projectId: projectId,
|
|
134
|
+
chatbot: this.chatbot,
|
|
135
|
+
message: this.message,
|
|
131
136
|
token: token,
|
|
132
137
|
supportRequest: supportRequest,
|
|
133
138
|
reply: this.reply,
|
|
@@ -194,12 +199,11 @@ class DirectivesChatbotPlug {
|
|
|
194
199
|
}
|
|
195
200
|
|
|
196
201
|
async process(directive) {
|
|
197
|
-
|
|
202
|
+
console.log(".process(directive):", JSON.stringify(directive));
|
|
198
203
|
let context = this.context;
|
|
199
204
|
// console.log(".this.context.reply", JSON.stringify(this.context.reply));
|
|
200
205
|
if (directive) {
|
|
201
206
|
if (context.log) {
|
|
202
|
-
console.log("..process(directive):", JSON.stringify(directive));
|
|
203
207
|
console.log("directive['name']:", directive["name"]);
|
|
204
208
|
}
|
|
205
209
|
}
|
|
@@ -207,6 +211,29 @@ class DirectivesChatbotPlug {
|
|
|
207
211
|
if (directive && directive.name) {
|
|
208
212
|
directive_name = directive.name.toLowerCase();
|
|
209
213
|
}
|
|
214
|
+
if (directive && directive.action) {
|
|
215
|
+
console.log("Checking locks", JSON.stringify(directive));
|
|
216
|
+
// try {
|
|
217
|
+
const action_id = directive.action["_tdActionId"];
|
|
218
|
+
console.log("Checking locked directive:", action_id, "for request:", this.supportRequest.request_id);
|
|
219
|
+
const locked_action_id = await this.chatbot.currentLockedAction(this.supportRequest.request_id);
|
|
220
|
+
console.log("locked_action_id:", locked_action_id);
|
|
221
|
+
if ( locked_action_id && (locked_action_id !== action_id) ) {
|
|
222
|
+
console.log("Found locked action:", locked_action_id, "Skipping this action:", action_id);
|
|
223
|
+
let next_dir = await this.nextDirective(this.directives);
|
|
224
|
+
this.process(next_dir);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// go on
|
|
229
|
+
console.log("Going on to next directive...");
|
|
230
|
+
}
|
|
231
|
+
// }
|
|
232
|
+
// catch(error) {
|
|
233
|
+
// console.error("Error on locks:", error);
|
|
234
|
+
// }
|
|
235
|
+
|
|
236
|
+
}
|
|
210
237
|
if (directive == null || (directive !== null && directive["name"] === undefined)) {
|
|
211
238
|
if (context.log) { console.log("stop process(). directive is (null?):", directive);}
|
|
212
239
|
this.theend();
|
|
@@ -243,7 +270,7 @@ class DirectivesChatbotPlug {
|
|
|
243
270
|
});
|
|
244
271
|
}
|
|
245
272
|
else if (directive_name === Directives.REPLY) {
|
|
246
|
-
|
|
273
|
+
console.log("...DirReply");
|
|
247
274
|
new DirReply(context).execute(directive, async () => {
|
|
248
275
|
let next_dir = await this.nextDirective(this.directives);
|
|
249
276
|
this.process(next_dir);
|
|
@@ -493,6 +520,27 @@ class DirectivesChatbotPlug {
|
|
|
493
520
|
}
|
|
494
521
|
});
|
|
495
522
|
}
|
|
523
|
+
else if (directive_name === Directives.FORM) {
|
|
524
|
+
console.log("...DirForm");
|
|
525
|
+
new DirForm(context).execute(directive, async (stop) => {
|
|
526
|
+
if (context.log) { console.log("stop on form?", stop);}
|
|
527
|
+
if (stop == true) {
|
|
528
|
+
if (context.log) { console.log("Stopping Actions on:", JSON.stringify(directive));}
|
|
529
|
+
this.theend();
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
let next_dir = await this.nextDirective(this.directives);
|
|
533
|
+
this.process(next_dir);
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
else if (directive_name === Directives.CAPTURE_USER_REPLY) {
|
|
538
|
+
console.log("...DirCaptureUserReply");
|
|
539
|
+
new DirCaptureUserReply(context).execute(directive, async () => {
|
|
540
|
+
let next_dir = await this.nextDirective(this.directives);
|
|
541
|
+
this.process(next_dir);
|
|
542
|
+
});
|
|
543
|
+
}
|
|
496
544
|
else if (directive_name === Directives.CODE) {
|
|
497
545
|
// console.log("...DirCode", directive);
|
|
498
546
|
new DirCode(context).execute(directive, async () => {
|
|
@@ -75,7 +75,8 @@ class DirAskGPT {
|
|
|
75
75
|
console.log("falseIntentAttributes",falseIntentAttributes )
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
const
|
|
78
|
+
const server_base_url = process.env.API_ENDPOINT || process.env.API_URL;
|
|
79
|
+
const kb_url = server_base_url + "/" + this.context.projectId + "/kbsettings";
|
|
79
80
|
if (this.log) { console.log("ApiEndpoint URL: ", kb_url); }
|
|
80
81
|
const KB_HTTPREQUEST = {
|
|
81
82
|
url: kb_url,
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
const { Filler } = require('../Filler');
|
|
2
|
+
const { TiledeskChatbot } = require('../../models/TiledeskChatbot');
|
|
3
|
+
const { DirIntent } = require('./DirIntent');
|
|
4
|
+
|
|
5
|
+
class DirCaptureUserReply {
|
|
6
|
+
constructor(context) {
|
|
7
|
+
if (!context) {
|
|
8
|
+
throw new Error('context object is mandatory.');
|
|
9
|
+
}
|
|
10
|
+
this.context = context;
|
|
11
|
+
this.reply = context.reply;
|
|
12
|
+
// reply = {
|
|
13
|
+
// actions: [
|
|
14
|
+
// {
|
|
15
|
+
// _tdActionType: 'askgpt',
|
|
16
|
+
// _tdActionTitle: 'gpt action',
|
|
17
|
+
// assignReplyTo: 'gpt_reply',
|
|
18
|
+
// assignSourceTo: 'gpt_source',
|
|
19
|
+
// kbid: 'XXX',
|
|
20
|
+
// trueIntent: '#SUCCESS',
|
|
21
|
+
// falseIntent: '#FAILURE',
|
|
22
|
+
// question: 'this is the question: ${last_user_message}'
|
|
23
|
+
// }
|
|
24
|
+
// ],
|
|
25
|
+
// attributes: {
|
|
26
|
+
// clienttimestamp: 1695548792706,
|
|
27
|
+
// intent_info: {
|
|
28
|
+
// intent_name: 'gpt success',
|
|
29
|
+
// intent_id: '00f93b97-89ee-466d-a09c-e47a18943057',
|
|
30
|
+
// is_fallback: false,
|
|
31
|
+
// confidence: undefined,
|
|
32
|
+
// question_payload: [Object],
|
|
33
|
+
// botId: 'botID',
|
|
34
|
+
// bot: [Object]
|
|
35
|
+
// },
|
|
36
|
+
// webhook: false
|
|
37
|
+
// }
|
|
38
|
+
// }
|
|
39
|
+
this.message = context.message;
|
|
40
|
+
this.tdclient = context.tdclient;
|
|
41
|
+
this.chatbot = context.chatbot;
|
|
42
|
+
this.tdcache = context.tdcache;
|
|
43
|
+
this.requestId = context.requestId;
|
|
44
|
+
this.intentDir = new DirIntent(context);
|
|
45
|
+
this.log = context.log;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
execute(directive, callback) {
|
|
49
|
+
let action;
|
|
50
|
+
if (directive.action) {
|
|
51
|
+
action = directive.action;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
console.error("Incorrect directive:", JSON.stringify(directive));
|
|
55
|
+
callback();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this.go(action, () => {
|
|
59
|
+
callback();
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async go(action, callback) {
|
|
64
|
+
const goToIntent = action.goToIntent;
|
|
65
|
+
console.log("(DirCaptureUserReply) goToIntent:", goToIntent);
|
|
66
|
+
let lockedAction = await this.chatbot.currentLockedAction(this.requestId);
|
|
67
|
+
console.log("(DirCaptureUserReply) lockedAction:", lockedAction);
|
|
68
|
+
if (!lockedAction) {
|
|
69
|
+
console.log("(DirCaptureUserReply) !lockedAction");
|
|
70
|
+
const intent_name = this.reply.attributes.intent_info.intent_name
|
|
71
|
+
const actionId = action["_tdActionId"];
|
|
72
|
+
console.log("(DirCaptureUserReply) intent_name:", intent_name);
|
|
73
|
+
console.log("(DirCaptureUserReply) actionId:", actionId);
|
|
74
|
+
await this.chatbot.lockIntent(this.requestId, intent_name);
|
|
75
|
+
console.log("(DirCaptureUserReply) lockIntent");
|
|
76
|
+
await this.chatbot.lockAction(this.requestId, actionId);
|
|
77
|
+
console.log("(DirCaptureUserReply) lockAction");
|
|
78
|
+
let _lockedAction = await this.chatbot.currentLockedAction(this.requestId);
|
|
79
|
+
let _lockedIntent = await this.chatbot.currentLockedIntent(this.requestId);
|
|
80
|
+
console.log("(DirCaptureUserReply) _lockedAction", _lockedAction)
|
|
81
|
+
console.log("(DirCaptureUserReply) _lockedIntent", _lockedIntent)
|
|
82
|
+
callback();
|
|
83
|
+
return;
|
|
84
|
+
} else {
|
|
85
|
+
try {
|
|
86
|
+
await this.chatbot.unlockIntent(this.requestId);
|
|
87
|
+
await this.chatbot.unlockAction(this.requestId);
|
|
88
|
+
console.log("unlo")
|
|
89
|
+
}
|
|
90
|
+
catch(e) {
|
|
91
|
+
console.error("Erro", e)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const user_reply = this.message.text;
|
|
97
|
+
if (this.context.tdcache) {
|
|
98
|
+
if (action.assignResultTo) {
|
|
99
|
+
if (this.log) {console.log("assign assignResultTo:", action.assignResultTo);}
|
|
100
|
+
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignResultTo, user_reply);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (callback) {
|
|
105
|
+
console.log("(DirCaptureUserReply) #executeGoTo(goToIntent)", goToIntent)
|
|
106
|
+
this.#executeGoTo(goToIntent, () => {
|
|
107
|
+
callback(); // continue the flow
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch(error) {
|
|
112
|
+
console.error("error is", error);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#executeGoTo(intent, callback) {
|
|
117
|
+
let goToIntentDirective = null;
|
|
118
|
+
if (intent) {
|
|
119
|
+
goToIntentDirective = DirIntent.intentDirectiveFor(intent);
|
|
120
|
+
}
|
|
121
|
+
this.intentDir.execute(goToIntentDirective, () => {
|
|
122
|
+
callback();
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = { DirCaptureUserReply };
|
|
@@ -32,24 +32,75 @@ class DirDepartment {
|
|
|
32
32
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
35
|
+
// example dept
|
|
36
|
+
// {
|
|
37
|
+
// "routing": "assigned",
|
|
38
|
+
// "default": false,
|
|
39
|
+
// "status": 0,
|
|
40
|
+
// "_id": "65204737f8c0cf002cf41a60",
|
|
41
|
+
// "name": "dep2",
|
|
42
|
+
// "id_project": "65203e12f8c0cf002cf4110b",
|
|
43
|
+
// "createdBy": "5e09d16d4d36110017506d7f",
|
|
44
|
+
// "tags": [],
|
|
45
|
+
// "createdAt": "2023-10-06T17:43:19.991Z",
|
|
46
|
+
// "updatedAt": "2023-10-07T15:28:31.775Z",
|
|
47
|
+
// "__v": 0,
|
|
48
|
+
// "id_bot": "65204767f8c0cf002cf41ada",
|
|
49
|
+
// "id_group": null,
|
|
50
|
+
// "hasBot": true,
|
|
51
|
+
// "id": "65204737f8c0cf002cf41a60"
|
|
40
52
|
// }
|
|
41
53
|
|
|
42
54
|
go(action, callback) {
|
|
43
|
-
console.log("Switching to department:", action.depName);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
55
|
+
if (this.log) {console.log("Switching to department:", action.depName);}
|
|
56
|
+
const depName = action.depName;
|
|
57
|
+
this.moveToDepartment(this.requestId, depName, (deps) => {
|
|
58
|
+
if (!deps) {
|
|
59
|
+
if (this.log) {console.log("Dep not found");}
|
|
60
|
+
callback();
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
if (this.log) {console.log("Switched to dept:", depName, "action:", JSON.stringify(action));}
|
|
64
|
+
if (action.triggerBot) {
|
|
65
|
+
let dep = null;
|
|
66
|
+
let i;
|
|
67
|
+
for (i = 0; i < deps.length; i++) {
|
|
68
|
+
let d = deps[i];
|
|
69
|
+
if (d.name.toLowerCase() === depName.toLowerCase()) {
|
|
70
|
+
dep = d;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (dep && dep.hasBot === true && dep.id_bot) {
|
|
75
|
+
if (this.log) {console.log("Sending hidden /start message to bot in dept");}
|
|
76
|
+
const message = {
|
|
77
|
+
type: "text",
|
|
78
|
+
text: "/start",
|
|
79
|
+
attributes : {
|
|
80
|
+
subtype: "info"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
this.tdclient.sendSupportMessage(
|
|
84
|
+
this.requestId,
|
|
85
|
+
message, (err) => {
|
|
86
|
+
if (err) {
|
|
87
|
+
console.error("Error sending hidden message:", err.message);
|
|
88
|
+
}
|
|
89
|
+
if (this.log) {console.log("Hidden message sent.");}
|
|
90
|
+
callback();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
if (this.log) {console.log("No action.triggerBot");}
|
|
96
|
+
callback();
|
|
97
|
+
}
|
|
47
98
|
});
|
|
48
99
|
}
|
|
49
100
|
|
|
50
101
|
moveToDepartment(requestId, depName, callback) {
|
|
51
102
|
this.tdclient.getAllDepartments((err, deps) => {
|
|
52
|
-
if (this.log) {console.log("deps:", deps);}
|
|
103
|
+
if (this.log) {console.log("deps:", JSON.stringify(deps));}
|
|
53
104
|
if (err) {
|
|
54
105
|
console.error("getAllDepartments() error:", err);
|
|
55
106
|
callback();
|
|
@@ -72,7 +123,7 @@ class DirDepartment {
|
|
|
72
123
|
}
|
|
73
124
|
else {
|
|
74
125
|
console.log("DirDepartment response:",JSON.stringify(res));
|
|
75
|
-
callback();
|
|
126
|
+
callback(deps);
|
|
76
127
|
}
|
|
77
128
|
});
|
|
78
129
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const { Filler } = require('../Filler');
|
|
2
2
|
const { TiledeskChatbot } = require('../../models/TiledeskChatbot');
|
|
3
3
|
const { DirIntent } = require('./DirIntent');
|
|
4
|
-
const {
|
|
5
|
-
const { DirUnlockIntent } = require('../tiledeskChatbotPlugs/directives/DirUnlockIntent');
|
|
4
|
+
const { IntentForm } = require('../../models/IntentForm.js');
|
|
6
5
|
|
|
7
6
|
class DirForm {
|
|
8
7
|
constructor(context) {
|
|
@@ -11,6 +10,7 @@ class DirForm {
|
|
|
11
10
|
}
|
|
12
11
|
this.context = context;
|
|
13
12
|
this.tdclient = context.tdclient;
|
|
13
|
+
this.chatbot = context.chatbot;
|
|
14
14
|
this.tdcache = context.tdcache;
|
|
15
15
|
this.requestId = context.requestId;
|
|
16
16
|
this.intentDir = new DirIntent(context);
|
|
@@ -28,18 +28,17 @@ class DirForm {
|
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
this.go(action, (stop) => {
|
|
31
|
-
if (this.log) {console.log("(
|
|
31
|
+
if (this.log) {console.log("(DirForm, stop?", stop); }
|
|
32
32
|
callback(stop);
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
async go(action, callback) {
|
|
37
|
-
let intent_name = answerObj.intent_display_name
|
|
38
37
|
// THE FORM
|
|
39
38
|
// if (intent_name === "test_form_intent") {
|
|
40
|
-
//
|
|
39
|
+
// action.form = {
|
|
41
40
|
// "cancelCommands": ['reset', 'cancel'],
|
|
42
|
-
// "cancelReply": "Ok canceled!",
|
|
41
|
+
// "cancelReply": "Ok canceled!", // REMOVE
|
|
43
42
|
// "fields": [
|
|
44
43
|
// {
|
|
45
44
|
// "name": "userFullname",
|
|
@@ -60,15 +59,17 @@ class DirForm {
|
|
|
60
59
|
// ]
|
|
61
60
|
// };
|
|
62
61
|
// }
|
|
63
|
-
|
|
62
|
+
const trueIntent = action.trueIntent; // edit-end (success)
|
|
63
|
+
const falseIntent = action.falseIntent; // cancel
|
|
64
|
+
let form = action.form;
|
|
64
65
|
if (this.log) {
|
|
65
|
-
console.log("IntentForm.isValidForm(intent_form)", IntentForm.isValidForm(
|
|
66
|
+
console.log("IntentForm.isValidForm(intent_form)", IntentForm.isValidForm(form));
|
|
66
67
|
}
|
|
67
68
|
let clientUpdateUserFullname = null;
|
|
68
|
-
if (IntentForm.isValidForm(
|
|
69
|
-
await this.
|
|
69
|
+
if (IntentForm.isValidForm(form)) {
|
|
70
|
+
await this.chatbot.lockAction(this.requestId, action.action_id);
|
|
70
71
|
const user_reply = message.text;
|
|
71
|
-
let form_reply = await this.execIntentForm(user_reply,
|
|
72
|
+
let form_reply = await this.execIntentForm(user_reply, form);
|
|
72
73
|
// console.log("got form reply", form_reply)
|
|
73
74
|
if (!form_reply.canceled && form_reply.message) {
|
|
74
75
|
// console.log("Form replying for next field...");
|
|
@@ -80,7 +81,18 @@ class DirForm {
|
|
|
80
81
|
form_reply.message.attributes.fillParams = true;
|
|
81
82
|
form_reply.message.attributes.splits = true;
|
|
82
83
|
form_reply.message.attributes.markbot = true;
|
|
83
|
-
return form_reply.message;
|
|
84
|
+
// return form_reply.message;
|
|
85
|
+
|
|
86
|
+
this.context.tdclient.sendSupportMessage(
|
|
87
|
+
this.requestId,
|
|
88
|
+
form_reply.message,
|
|
89
|
+
(err) => {
|
|
90
|
+
if (err) {
|
|
91
|
+
console.error("Error sending form reply:", err.message);
|
|
92
|
+
}
|
|
93
|
+
if (this.log) {console.log("Form reply message sent.");}
|
|
94
|
+
callback(true);
|
|
95
|
+
});
|
|
84
96
|
}
|
|
85
97
|
else if (form_reply.end) {
|
|
86
98
|
if (this.log) {
|
|
@@ -88,43 +100,85 @@ class DirForm {
|
|
|
88
100
|
console.log("unlocking intent for request:", this.requestId);
|
|
89
101
|
console.log("populate data on lead:", JSON.stringify(lead));
|
|
90
102
|
}
|
|
91
|
-
this.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
const all_parameters = await this.allParameters();
|
|
99
|
-
// if (this.log) {console.log("We have all_parameters:", all_parameters)};
|
|
100
|
-
if (all_parameters && all_parameters["userFullname"]) {
|
|
101
|
-
clientUpdateUserFullname = all_parameters["userFullname"];
|
|
103
|
+
this.chatbot.unlockAction(this.requestId);
|
|
104
|
+
|
|
105
|
+
if (callback) {
|
|
106
|
+
this.#executeCondition(true, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, () => {
|
|
107
|
+
callback(false); // continue the flow
|
|
108
|
+
});
|
|
102
109
|
}
|
|
110
|
+
// TODO: INVOKE DIR_INTENT FOR END-FORM (SUCCESS)
|
|
111
|
+
// if (lead) {
|
|
112
|
+
// this.populatePrechatFormAndLead(lead._id, this.requestId);
|
|
113
|
+
// }
|
|
114
|
+
// else {
|
|
115
|
+
// if (this.log) {console.log("No lead. Skipping populatePrechatFormAndLead()");}
|
|
116
|
+
// }
|
|
117
|
+
// const all_parameters = await this.chatbot.allParameters();
|
|
118
|
+
// if (all_parameters && all_parameters["userFullname"]) {
|
|
119
|
+
// clientUpdateUserFullname = all_parameters["userFullname"];
|
|
120
|
+
// }
|
|
103
121
|
}
|
|
104
122
|
else if (form_reply.canceled) {
|
|
105
|
-
console.log("Form canceled.");
|
|
106
123
|
if (this.log) {console.log("unlocking intent due to canceling, for request", this.requestId);}
|
|
107
|
-
this.
|
|
108
|
-
|
|
109
|
-
//
|
|
110
|
-
if (
|
|
111
|
-
|
|
124
|
+
this.unlockAction(this.requestId);
|
|
125
|
+
|
|
126
|
+
// TODO: INVOKE DIR_INTENT FOR CANCEL.
|
|
127
|
+
if (callback) {
|
|
128
|
+
this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, () => {
|
|
129
|
+
callback(false); // continue the flow
|
|
130
|
+
});
|
|
112
131
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
132
|
+
|
|
133
|
+
// if (this.log) {console.log("sending form 'cancel' reply...", form_reply.message)}
|
|
134
|
+
// TODO: REMOVE CANCEL REPLY
|
|
135
|
+
// reply with this message (ex. please enter your fullname)
|
|
136
|
+
// if (!form_reply.message.attributes) {
|
|
137
|
+
// form_reply.message.attributes = {}
|
|
138
|
+
// }
|
|
139
|
+
// form_reply.message.attributes.fillParams = true;
|
|
140
|
+
// form_reply.message.attributes.splits = true;
|
|
141
|
+
// form_reply.message.attributes.directives = true;
|
|
116
142
|
// // used by the Clients to get some info about the intent that generated this reply
|
|
117
143
|
// form_reply.message.attributes.intent_display_name = faq.intent_display_name;
|
|
118
144
|
// form_reply.message.attributes.intent_id = faq.intent_id;
|
|
119
|
-
return form_reply.message
|
|
145
|
+
// return form_reply.message
|
|
120
146
|
}
|
|
121
147
|
}
|
|
122
148
|
// FORM END
|
|
123
149
|
}
|
|
124
150
|
|
|
125
|
-
async
|
|
126
|
-
|
|
127
|
-
|
|
151
|
+
async #executeCondition(result, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, callback) {
|
|
152
|
+
let trueIntentDirective = null;
|
|
153
|
+
if (trueIntent) {
|
|
154
|
+
trueIntentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
|
|
155
|
+
}
|
|
156
|
+
let falseIntentDirective = null;
|
|
157
|
+
if (falseIntent) {
|
|
158
|
+
falseIntentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
|
|
159
|
+
}
|
|
160
|
+
if (result === true) {
|
|
161
|
+
if (trueIntentDirective) {
|
|
162
|
+
this.intentDir.execute(trueIntentDirective, () => {
|
|
163
|
+
callback();
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
if (this.log) {console.log("No trueIntentDirective specified");}
|
|
168
|
+
callback();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
if (falseIntentDirective) {
|
|
173
|
+
this.intentDir.execute(falseIntentDirective, () => {
|
|
174
|
+
callback();
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
if (this.log) {console.log("No falseIntentDirective specified");}
|
|
179
|
+
callback();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
128
182
|
}
|
|
129
183
|
|
|
130
184
|
}
|
|
@@ -122,7 +122,7 @@ class DirJSONCondition {
|
|
|
122
122
|
if (falseIntentDirective) {
|
|
123
123
|
this.intentDir.execute(falseIntentDirective, () => {
|
|
124
124
|
// console.log("result === false. stopOnConditionMet?", stopOnConditionMet);
|
|
125
|
-
callback(stopOnConditionMet);
|
|
125
|
+
callback(stopOnConditionMet);
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
128
|
else {
|
|
@@ -24,12 +24,13 @@ class DirMessage {
|
|
|
24
24
|
this.projectId = context.projectId;
|
|
25
25
|
this.requestId = context.requestId;
|
|
26
26
|
this.token = context.token;
|
|
27
|
+
this.log = this.context.log;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
execute(directive, callback) {
|
|
30
31
|
let action;
|
|
31
32
|
if (directive.action) {
|
|
32
|
-
|
|
33
|
+
if (this.log) {console.log("got action:", JSON.stringify(action));}
|
|
33
34
|
action = directive.action;
|
|
34
35
|
if (!action.attributes) {
|
|
35
36
|
action.attributes = {}
|
|
@@ -47,7 +47,7 @@ class DirReply {
|
|
|
47
47
|
if (this.log) {
|
|
48
48
|
for (const [key, value] of Object.entries(requestAttributes)) {
|
|
49
49
|
const value_type = typeof value;
|
|
50
|
-
if (this.log) {console.log("(DirReply) request parameter:", key, "value:", value, "type:", value_type)}
|
|
50
|
+
// if (this.log) {console.log("(DirReply) request parameter:", key, "value:", value, "type:", value_type)}
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
const filler = new Filler();
|
|
@@ -233,11 +233,34 @@ class DirWebRequestV2 {
|
|
|
233
233
|
})
|
|
234
234
|
.catch( (err) => {
|
|
235
235
|
if (this.log) {
|
|
236
|
-
|
|
236
|
+
// FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - START
|
|
237
|
+
let cache = [];
|
|
238
|
+
let error_log = JSON.stringify(err, function(key, value) { // try to use a separate function
|
|
239
|
+
if (typeof value === 'object' && value != null) {
|
|
240
|
+
if (cache.indexOf(value) !== -1) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
cache.push(value);
|
|
244
|
+
}
|
|
245
|
+
return value;
|
|
246
|
+
});
|
|
247
|
+
console.error("An error occurred: ", error_log);
|
|
248
|
+
// FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - END
|
|
249
|
+
// console.error("An error occurred:", JSON.stringify(err));
|
|
237
250
|
}
|
|
238
251
|
if (callback) {
|
|
239
252
|
let status = 1000;
|
|
240
|
-
let
|
|
253
|
+
let cache = [];
|
|
254
|
+
let str_error = JSON.stringify(err, function(key, value) { // try to use a separate function
|
|
255
|
+
if (typeof value === 'object' && value != null) {
|
|
256
|
+
if (cache.indexOf(value) !== -1) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
cache.push(value);
|
|
260
|
+
}
|
|
261
|
+
return value;
|
|
262
|
+
});
|
|
263
|
+
let error = JSON.parse(str_error) // "status" disappears without this trick
|
|
241
264
|
let errorMessage = JSON.stringify(error);
|
|
242
265
|
if (error.status) {
|
|
243
266
|
status = error.status;
|
|
@@ -255,6 +278,7 @@ class DirWebRequestV2 {
|
|
|
255
278
|
}
|
|
256
279
|
});
|
|
257
280
|
}
|
|
281
|
+
|
|
258
282
|
}
|
|
259
283
|
|
|
260
284
|
module.exports = { DirWebRequestV2 };
|
|
@@ -36,7 +36,8 @@ class DirWhatsappByAttribute {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
if (process.env.API_URL) {
|
|
39
|
-
whatsapp_api_url =
|
|
39
|
+
whatsapp_api_url = "https://tiledesk-whatsapp-app-pre.giovannitroisi3.repl.co/api";
|
|
40
|
+
// whatsapp_api_url = process.env.API_URL + "/modules/whatsapp";
|
|
40
41
|
console.log("(Tilebot) DirWhatsappByAttribute whatsapp_api_url: ", whatsapp_api_url);
|
|
41
42
|
} else {
|
|
42
43
|
console.error("(Tilebot) ERROR Missing whatsapp_api_url. Unable to use action WhatsApp By Attributes");
|
|
@@ -28,6 +28,8 @@ class Directives {
|
|
|
28
28
|
static WHATSAPP_ATTRIBUTE = 'whatsapp_attribute';
|
|
29
29
|
static ASK_GPT = "askgpt";
|
|
30
30
|
static GPT_TASK = "gpt_task";
|
|
31
|
+
static FORM = "form";
|
|
32
|
+
static CAPTURE_USER_REPLY = "capture_user_reply";
|
|
31
33
|
|
|
32
34
|
// static WHEN_ONLINE_MOVE_TO_AGENT = "whenonlinemovetoagent"; // DEPRECATED?
|
|
33
35
|
// static WHEN_OFFLINE_HOURS = "whenofflinehours"; // DEPRECATED // adds a message on top of the original message when offline hours opts: --replace
|