@tiledesk/tiledesk-tybot-connector 0.1.21 → 0.1.22
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 +4 -1
- package/ExtUtil.js +1 -0
- package/index.js +11 -2
- package/package.json +1 -1
- package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +5 -7
- package/tiledeskChatbotPlugs/directives/DirDeflectToHelpCenter.js +6 -6
- package/tiledeskChatbotPlugs/directives/DirDepartment.js +52 -0
- package/models/MongoDBIntentsDataSource.js +0 -22
- package/models/StaticIntentsDataSource.js +0 -110
- package/models/TiledeskChatbot_Intents_Adapter.js +0 -406
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# Tiledesk tybotRoute
|
|
2
2
|
|
|
3
|
-
**npm @tiledesk/tiledesk-tybot-connector@0.1.
|
|
3
|
+
**npm @tiledesk/tiledesk-tybot-connector@0.1.22**
|
|
4
4
|
|
|
5
5
|
available on:
|
|
6
6
|
▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
|
|
7
7
|
|
|
8
|
+
### 0.1.22
|
|
9
|
+
- introduced new DirDepartment class
|
|
10
|
+
|
|
8
11
|
### 0.1.21
|
|
9
12
|
- fixed orginal_text unused var that creating problems in DirOfflineHours
|
|
10
13
|
|
package/ExtUtil.js
CHANGED
|
@@ -16,6 +16,7 @@ const { WebhookChatbotPlug } = require('@tiledesk/tiledesk-chatbot-plugs/Webhook
|
|
|
16
16
|
class ExtUtil {
|
|
17
17
|
|
|
18
18
|
static async execPipelineExt(request, static_bot_answer, directivesPlug, tdcache, log) {
|
|
19
|
+
console.log("Buuu")
|
|
19
20
|
const messagePipeline = new MessagePipeline(static_bot_answer, null);
|
|
20
21
|
//const webhookurl = bot.webhook_url;
|
|
21
22
|
//messagePipeline.addPlug(new WebhookChatbotPlug(message.request, webhookurl, token));
|
package/index.js
CHANGED
|
@@ -135,9 +135,18 @@ router.post('/ext/:projectId/requests/:requestId/messages', async (req, res) =>
|
|
|
135
135
|
request = await tdclient.getRequestById(requestId);
|
|
136
136
|
if (log) {console.log("(No tdcache) Got request with APIs");}
|
|
137
137
|
}
|
|
138
|
-
let directivesPlug = new DirectivesChatbotPlug(
|
|
138
|
+
let directivesPlug = new DirectivesChatbotPlug(
|
|
139
|
+
{
|
|
140
|
+
supportRequest: request,
|
|
141
|
+
TILEDESK_API_ENDPOINT: APIURL,
|
|
142
|
+
token: token,
|
|
143
|
+
HELP_CENTER_API_ENDPOINT: process.env.HELP_CENTER_API_ENDPOINT,
|
|
144
|
+
cache: tdcache,
|
|
145
|
+
log: true
|
|
146
|
+
}
|
|
147
|
+
);
|
|
139
148
|
// PIPELINE-EXT
|
|
140
|
-
const bot_answer = await ExtUtil.execPipelineExt(request, answer, directivesPlug, tdcache,
|
|
149
|
+
const bot_answer = await ExtUtil.execPipelineExt(request, answer, directivesPlug, tdcache, true);
|
|
141
150
|
//const bot_answer = answer;
|
|
142
151
|
tdclient.sendSupportMessage(requestId, bot_answer, () => {
|
|
143
152
|
directivesPlug.processDirectives(() => {
|
package/package.json
CHANGED
|
@@ -8,6 +8,7 @@ const { DirWait } = require('./directives/DirWait');
|
|
|
8
8
|
const { DirReplaceBot } = require('./directives/DirReplaceBot');
|
|
9
9
|
const { DirLockIntent } = require('./directives/DirLockIntent');
|
|
10
10
|
const { DirUnlockIntent } = require('./directives/DirUnlockIntent');
|
|
11
|
+
const { DirDepartment } = require('./directives/DirDepartment');
|
|
11
12
|
const { Directives } = require('./directives/Directives');
|
|
12
13
|
|
|
13
14
|
class DirectivesChatbotPlug {
|
|
@@ -62,7 +63,7 @@ class DirectivesChatbotPlug {
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
/*
|
|
66
67
|
moveToDepartment(tdclient, requestId, depName, callback) {
|
|
67
68
|
tdclient.getAllDepartments((err, deps) => {
|
|
68
69
|
console.log("deps:", deps, err);
|
|
@@ -91,7 +92,7 @@ class DirectivesChatbotPlug {
|
|
|
91
92
|
});
|
|
92
93
|
}
|
|
93
94
|
});
|
|
94
|
-
}
|
|
95
|
+
}*/
|
|
95
96
|
|
|
96
97
|
processDirectives(theend) {
|
|
97
98
|
const directives = this.directives;
|
|
@@ -137,9 +138,8 @@ class DirectivesChatbotPlug {
|
|
|
137
138
|
if (directive.parameter) {
|
|
138
139
|
dep_name = directive.parameter;
|
|
139
140
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
console.log("moved to department:", dep_name);
|
|
141
|
+
const departmentDir = new DirDepartment({tdclient: tdclient, log: false});
|
|
142
|
+
departmentDir.execute(requestId, dep_name, () => {
|
|
143
143
|
process(nextDirective());
|
|
144
144
|
});
|
|
145
145
|
}
|
|
@@ -154,7 +154,6 @@ class DirectivesChatbotPlug {
|
|
|
154
154
|
subtype: "info"
|
|
155
155
|
}
|
|
156
156
|
};
|
|
157
|
-
console.log("Message:", message)
|
|
158
157
|
tdclient.sendSupportMessage(requestId, message, () => {
|
|
159
158
|
process(nextDirective());
|
|
160
159
|
});
|
|
@@ -167,7 +166,6 @@ class DirectivesChatbotPlug {
|
|
|
167
166
|
});
|
|
168
167
|
}
|
|
169
168
|
else if (directive_name === Directives.AGENT) {
|
|
170
|
-
tdclient.log = false;
|
|
171
169
|
const agentDir = new DirMoveToAgent(tdclient);
|
|
172
170
|
directive.whenOnlineOnly = false;
|
|
173
171
|
agentDir.execute(directive, requestId, depId, () => {
|
|
@@ -44,7 +44,7 @@ class DirDeflectToHelpCenter {
|
|
|
44
44
|
APIKEY: "__",
|
|
45
45
|
APIURL: this.helpcenter_api_endpoint,
|
|
46
46
|
projectId: this.projectId,
|
|
47
|
-
log:
|
|
47
|
+
log: true
|
|
48
48
|
});
|
|
49
49
|
if (!workspace_id) {
|
|
50
50
|
try {
|
|
@@ -52,10 +52,10 @@ class DirDeflectToHelpCenter {
|
|
|
52
52
|
const workspaces = await helpcenter.allWorkspaces();
|
|
53
53
|
if (workspaces.length > 0) {
|
|
54
54
|
workspace_id = workspaces[0]._id;
|
|
55
|
-
|
|
55
|
+
console.log("First Workspace selected", workspaces[0]);
|
|
56
56
|
}
|
|
57
57
|
else {
|
|
58
|
-
|
|
58
|
+
console.log("No Workspace found");
|
|
59
59
|
completion();
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -64,12 +64,12 @@ class DirDeflectToHelpCenter {
|
|
|
64
64
|
completion();
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
console.log("searching on workspace_id:", workspace_id);
|
|
68
68
|
try {
|
|
69
69
|
const results = await helpcenter.search(workspace_id, original_text, maxresults);
|
|
70
70
|
if (results && results.length > 0) {
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
console.log("Successfully got results", results);
|
|
72
|
+
console.log("Sending REPL", hc_reply);
|
|
73
73
|
pipeline.message.text = hc_reply;
|
|
74
74
|
results.forEach(content => {
|
|
75
75
|
if (content.url.charAt(content.url.length -1) != "/") {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
class DirDepartment {
|
|
3
|
+
|
|
4
|
+
constructor(config) {
|
|
5
|
+
if (!config.tdclient) {
|
|
6
|
+
throw new Error('tdclient (TiledeskClient) object is mandatory.');
|
|
7
|
+
}
|
|
8
|
+
this.tdclient = config.tdclient;
|
|
9
|
+
this.log = config.log;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
moveToDepartment(requestId, depName, callback) {
|
|
13
|
+
this.tdclient.getAllDepartments((err, deps) => {
|
|
14
|
+
if (this.log) {console.log("deps:", deps, err);}
|
|
15
|
+
if (err) {
|
|
16
|
+
console.error("getAllDepartments() error:", err);
|
|
17
|
+
callback(err);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
let dep = null;
|
|
21
|
+
let i;
|
|
22
|
+
for (i = 0; i < deps.length; i++) {
|
|
23
|
+
let d = deps[i];
|
|
24
|
+
if (d.name.toLowerCase() === depName.toLowerCase()) {
|
|
25
|
+
dep = d;
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (dep) {
|
|
30
|
+
this.tdclient.updateRequestDepartment(requestId, dep._id, null, (err) => {
|
|
31
|
+
if (err) {
|
|
32
|
+
console.error("An error:", err);
|
|
33
|
+
callback(err);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
callback();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
execute(requestId, dep_name, callback) {
|
|
44
|
+
if (this.log) {console.log("DirDepartment:", dep_name);}
|
|
45
|
+
this.moveToDepartment(requestId, dep_name, () => {
|
|
46
|
+
callback();
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { DirDepartment };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
class StaticIntentsQueryAdapter {
|
|
2
|
-
|
|
3
|
-
constructor() {
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
async getByExactMatch(text) {
|
|
7
|
-
const intent_display_name = questions_intent[text];
|
|
8
|
-
if (intent_display_name) {
|
|
9
|
-
return intents[intent_display_name];
|
|
10
|
-
}
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async getByNLP(text) {
|
|
15
|
-
return getByExactMatch(text);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async getByIntentName(intentName) {
|
|
19
|
-
return questions_intent[text];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
class StaticIntentsDataSource {
|
|
2
|
-
|
|
3
|
-
constructor(intentsDataSource) {
|
|
4
|
-
if (intentsDataSource) {
|
|
5
|
-
this.intentsDataSource = intentsDataSource;
|
|
6
|
-
}
|
|
7
|
-
else {
|
|
8
|
-
this.intentsDataSource = defaultIntentsSataSource;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async getByExactMatch(text) {
|
|
13
|
-
const intent_display_name = questions_intent[text];
|
|
14
|
-
if (intent_display_name) {
|
|
15
|
-
return intents[intent_display_name];
|
|
16
|
-
}
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async getByNLP(text) {
|
|
21
|
-
return getByExactMatch(text);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async getByIntentName(intentName) {
|
|
25
|
-
return questions_intent[text];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const defaultIntentsSataSource = {
|
|
31
|
-
"intents" = {
|
|
32
|
-
"intent1": {
|
|
33
|
-
intent_display_name: "intent1",
|
|
34
|
-
questions: [
|
|
35
|
-
"intent1 question1",
|
|
36
|
-
"intent1 question2"
|
|
37
|
-
],
|
|
38
|
-
answer: "reply to intent1"
|
|
39
|
-
},
|
|
40
|
-
"intent2": {
|
|
41
|
-
intent_display_name: "intent1",
|
|
42
|
-
questions: [
|
|
43
|
-
"intent2 question1",
|
|
44
|
-
"intent2 question2"
|
|
45
|
-
],
|
|
46
|
-
answer: "reply to intent2"
|
|
47
|
-
},
|
|
48
|
-
"intent3": {
|
|
49
|
-
intent_display_name: "intent3",
|
|
50
|
-
questions: [
|
|
51
|
-
"intent3 question1",
|
|
52
|
-
"intent3 question2"
|
|
53
|
-
],
|
|
54
|
-
answer: "reply to intent3"
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
"questions_intent": {
|
|
58
|
-
|
|
59
|
-
"intent1 question1": "intent1",
|
|
60
|
-
"intent1 question2": "intent1",
|
|
61
|
-
|
|
62
|
-
"intent2 question1": "intent2",
|
|
63
|
-
"intent2 question2": "intent2",
|
|
64
|
-
|
|
65
|
-
"intent3 question1": "intent3",
|
|
66
|
-
"intent3 question2": "intent3"
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const intents = {
|
|
72
|
-
"intent1": {
|
|
73
|
-
intent_display_name: "intent1",
|
|
74
|
-
questions: [
|
|
75
|
-
"intent1 question1",
|
|
76
|
-
"intent1 question2"
|
|
77
|
-
],
|
|
78
|
-
answer: "reply to intent1"
|
|
79
|
-
},
|
|
80
|
-
"intent2": {
|
|
81
|
-
intent_display_name: "intent1",
|
|
82
|
-
questions: [
|
|
83
|
-
"intent2 question1",
|
|
84
|
-
"intent2 question2"
|
|
85
|
-
],
|
|
86
|
-
answer: "reply to intent2"
|
|
87
|
-
},
|
|
88
|
-
"intent3": {
|
|
89
|
-
intent_display_name: "intent3",
|
|
90
|
-
questions: [
|
|
91
|
-
"intent3 question1",
|
|
92
|
-
"intent3 question2"
|
|
93
|
-
],
|
|
94
|
-
answer: "reply to intent3"
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const questions_intent = {
|
|
99
|
-
|
|
100
|
-
"intent1 question1": "intent1",
|
|
101
|
-
"intent1 question2": "intent1",
|
|
102
|
-
|
|
103
|
-
"intent2 question1": "intent2",
|
|
104
|
-
"intent2 question2": "intent2",
|
|
105
|
-
|
|
106
|
-
"intent3 question1": "intent3",
|
|
107
|
-
"intent3 question2": "intent3"
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
module.exports = { StaticIntentsDataSource }
|
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
let Faq = require('./faq');
|
|
2
|
-
let Faq_kb = require('./faq_kb');
|
|
3
|
-
const { ExtApi } = require('../ExtApi.js');
|
|
4
|
-
const { MessagePipeline } = require('../tiledeskChatbotPlugs/MessagePipeline');
|
|
5
|
-
const { DirectivesChatbotPlug } = require('../tiledeskChatbotPlugs/DirectivesChatbotPlug');
|
|
6
|
-
const { WebhookChatbotPlug } = require('../tiledeskChatbotPlugs/WebhookChatbotPlug');
|
|
7
|
-
const { TiledeskClient } = require('@tiledesk/tiledesk-client');
|
|
8
|
-
const { IntentForm } = require('./IntentForm.js');
|
|
9
|
-
|
|
10
|
-
class TiledeskChatbot {
|
|
11
|
-
|
|
12
|
-
constructor(config) {
|
|
13
|
-
this.botId = config.botId;
|
|
14
|
-
this.token = config.token;
|
|
15
|
-
this.faq_kb = config.faq_kb;
|
|
16
|
-
this.tdcache = config.tdcache;
|
|
17
|
-
this.APIURL = config.APIURL;
|
|
18
|
-
this.APIKEY = config.APIKEY;
|
|
19
|
-
this.requestId = config.requestId;
|
|
20
|
-
this.projectId = config.projectId;
|
|
21
|
-
this.log = config.log;
|
|
22
|
-
this.intentsDataSource = config.intentsDataSource
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async replyToMessage(message, callback) {
|
|
26
|
-
return new Promise( async (resolve, reject) => {
|
|
27
|
-
|
|
28
|
-
const bot = await Faq_kb.findById(this.botId).select('+secret').exec();
|
|
29
|
-
if (this.log) {console.log("bot:", bot);}
|
|
30
|
-
|
|
31
|
-
const locked_intent = await this.currentLockedIntent(this.requestId);
|
|
32
|
-
if (this.log) {console.log("got locked intent", locked_intent)}
|
|
33
|
-
if (locked_intent) {
|
|
34
|
-
const tdclient = new TiledeskClient({
|
|
35
|
-
projectId: message.id_project,
|
|
36
|
-
token: this.token,
|
|
37
|
-
APIURL: this.APIURL,
|
|
38
|
-
APIKEY: this.APIKEY,
|
|
39
|
-
log: false
|
|
40
|
-
});
|
|
41
|
-
const faqs = await tdclient.getIntents(this.botId, locked_intent, 0, 0, null);
|
|
42
|
-
if (this.log) {console.log("locked intent. got faqs", faqs)}
|
|
43
|
-
let reply = await this.execIntent(faqs, this.botId, message, bot);
|
|
44
|
-
resolve(reply);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
// CREATE TOKEN
|
|
48
|
-
//var botWithSecret = await Faq_kb.findById(bot._id).select('+secret').exec();
|
|
49
|
-
/*
|
|
50
|
-
let signOptions = {
|
|
51
|
-
issuer: 'https://tiledesk.com',
|
|
52
|
-
subject: 'bot',
|
|
53
|
-
audience: 'https://tiledesk.com/bots/'+bot._id,
|
|
54
|
-
jwtid: uuidv4()
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// DEPRECATED, REMOVE
|
|
58
|
-
const bot_token = jwt.sign(bot.toObject(), bot.secret, signOptions);
|
|
59
|
-
//console.log("bot_token:", bot_token);
|
|
60
|
-
*/
|
|
61
|
-
// SETUP EXACT MATCH
|
|
62
|
-
let query = { "id_project": this.projectId, "id_faq_kb": this.botId, "question": message.text };
|
|
63
|
-
// BUT CHECKING ACTION BUTTON...
|
|
64
|
-
if (message.attributes && message.attributes.action) {
|
|
65
|
-
var action = message.attributes.action;
|
|
66
|
-
var action_parameters_index = action.indexOf("?");
|
|
67
|
-
if (action_parameters_index > -1) {
|
|
68
|
-
action = action.substring(0, action_parameters_index);
|
|
69
|
-
}
|
|
70
|
-
query = { "id_project": this.projectId, "id_faq_kb": botId, "intent_display_name": action };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// SEARCH INTENTS
|
|
74
|
-
Faq.find(query).lean().exec(async (err, faqs) => {
|
|
75
|
-
if (err) {
|
|
76
|
-
return console.error("Error getting faq object.", err);
|
|
77
|
-
}
|
|
78
|
-
if (faqs && faqs.length > 0 && faqs[0].answer) {
|
|
79
|
-
if (this.log) {console.log("EXACT MATCH OR ACTION FAQ:", faqs[0]);}
|
|
80
|
-
let reply = await this.execIntent(faqs, this.botId, message, bot);
|
|
81
|
-
resolve(reply);
|
|
82
|
-
//resolve(this.execIntent(faqs, this.botId, message, bot)); // bot_token
|
|
83
|
-
}
|
|
84
|
-
else { // FULL TEXT
|
|
85
|
-
if (this.log) {console.log("NLP decode intent...");}
|
|
86
|
-
query = { "id_project": this.projectId, "id_faq_kb": this.botId };
|
|
87
|
-
var mongoproject = undefined;
|
|
88
|
-
var sort = undefined;
|
|
89
|
-
var search_obj = { "$search": message.text };
|
|
90
|
-
|
|
91
|
-
if (this.faq_kb.language) {
|
|
92
|
-
search_obj["$language"] = this.faq_kb.language;
|
|
93
|
-
}
|
|
94
|
-
query.$text = search_obj;
|
|
95
|
-
//console.debug("fulltext search query", query);
|
|
96
|
-
|
|
97
|
-
mongoproject = { score: { $meta: "textScore" } };
|
|
98
|
-
sort = { score: { $meta: "textScore" } }
|
|
99
|
-
// DA QUI RECUPERO LA RISPOSTA DATO (ID: SE EXT_AI) (QUERY FULLTEXT SE NATIVE-BASIC-AI)
|
|
100
|
-
Faq.find(query, mongoproject).sort(sort).lean().exec(async (err, faqs) => {
|
|
101
|
-
if (this.log) {console.log("Found:", faqs);}
|
|
102
|
-
if (err) {
|
|
103
|
-
console.error("Error:", err);
|
|
104
|
-
}
|
|
105
|
-
if (faqs && faqs.length > 0 && faqs[0].answer) {
|
|
106
|
-
let reply = await this.execIntent(faqs, this.botId, message, bot);
|
|
107
|
-
resolve(reply);
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
// fallback
|
|
111
|
-
const fallbackIntent = await this.getIntentByDisplayName("defaultFallback", bot);
|
|
112
|
-
const faqs = [fallbackIntent];
|
|
113
|
-
let reply = await this.execIntent(faqs, this.botId, message, bot);
|
|
114
|
-
resolve(reply); // bot_token
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
getIntentByDisplayName(name, bot) {
|
|
123
|
-
return new Promise((resolve, reject) => {
|
|
124
|
-
var query = { "id_project": bot.id_project, "id_faq_kb": bot._id, "intent_display_name": name};
|
|
125
|
-
if (this.log) {console.debug('query', query);}
|
|
126
|
-
Faq.find(query).lean().exec( (err, faqs) => {
|
|
127
|
-
if (err) {
|
|
128
|
-
return reject(err);
|
|
129
|
-
}
|
|
130
|
-
if (this.log) {console.debug("faqs", faqs);}
|
|
131
|
-
if (faqs && faqs.length > 0) {
|
|
132
|
-
const intent = faqs[0];
|
|
133
|
-
return resolve(intent);
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
return resolve(null);
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async execIntent(faqs, botId, message, bot) {
|
|
143
|
-
answerObj = faqs[0];
|
|
144
|
-
let sender = 'bot_' + botId;
|
|
145
|
-
var answerObj;
|
|
146
|
-
answerObj.score = 100; //exact search not set score
|
|
147
|
-
|
|
148
|
-
const requestId = message.request.request_id;
|
|
149
|
-
const projectId = message.id_project;
|
|
150
|
-
if (this.log) {
|
|
151
|
-
console.log("requestId:", requestId)
|
|
152
|
-
console.log("token:", this.token)
|
|
153
|
-
console.log("projectId:", projectId)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (this.tdcache) {
|
|
157
|
-
const requestKey = "tilebot:" + requestId
|
|
158
|
-
// best effort, do not "await", go on, trust redis speed.
|
|
159
|
-
this.tdcache.setJSON(requestKey, message.request);
|
|
160
|
-
}
|
|
161
|
-
// /ext/:projectId/requests/:requestId/messages ENDPOINT COINCIDES
|
|
162
|
-
// with API_ENDPOINT (APIRURL) ONLY WHEN THE TYBOT ROUTE IS HOSTED
|
|
163
|
-
// ON THE MAIN SERVER. OTHERWISE WE USE TYBOT_ROUTE TO SPECIFY
|
|
164
|
-
// THE ALTERNATIVE ROUTE.
|
|
165
|
-
let extEndpoint = `${this.APIURL}/modules/tilebot/`;
|
|
166
|
-
if (process.env.TYBOT_ENDPOINT) {
|
|
167
|
-
extEndpoint = `${process.env.TYBOT_ENDPOINT}`;
|
|
168
|
-
}
|
|
169
|
-
const apiext = new ExtApi({
|
|
170
|
-
ENDPOINT: extEndpoint,
|
|
171
|
-
log: this.log
|
|
172
|
-
});
|
|
173
|
-
console.log("the form...")
|
|
174
|
-
|
|
175
|
-
// THE FORM
|
|
176
|
-
|
|
177
|
-
let intent_name = answerObj.intent_display_name
|
|
178
|
-
// THE FORM
|
|
179
|
-
if (intent_name === "test_form_intent") {
|
|
180
|
-
answerObj.form = {
|
|
181
|
-
"cancelCommands": ['annulla', 'cancella', 'reset', 'cancel'],
|
|
182
|
-
"cancelReply": "Ok annullato!",
|
|
183
|
-
"fields": [
|
|
184
|
-
{
|
|
185
|
-
"name": "userFullname",
|
|
186
|
-
"type": "text",
|
|
187
|
-
"label": "What is your name?\n* Andrea\n* Marco\n* Mirco\n* Luca Leo"
|
|
188
|
-
},{
|
|
189
|
-
"name": "companyName",
|
|
190
|
-
"type": "text",
|
|
191
|
-
"label": "Thank you ${userFullname}! What is your Company name?\n* Tiledesk\n* Frontiere21"
|
|
192
|
-
},
|
|
193
|
-
{
|
|
194
|
-
"name": "userEmail",
|
|
195
|
-
"type": "text",
|
|
196
|
-
"regex": "/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$/",
|
|
197
|
-
"label": "Hi ${userFullname} from ${companyName}\n\nJust one last question\n\nYour email 🙂\n* andrea@libero.it\n* andrea@tiledesk.com",
|
|
198
|
-
"errorLabel": "${userFullname} this email address is invalid\n\nCan you insert a correct email address?"
|
|
199
|
-
}
|
|
200
|
-
]
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
let intent_form = answerObj.form;
|
|
204
|
-
if (intent_form) {
|
|
205
|
-
await this.lockIntent(requestId, intent_name);
|
|
206
|
-
const user_reply = message.text;
|
|
207
|
-
//const intent_answer = answerObj.answer; //req.body.payload.text;
|
|
208
|
-
let form_reply = await this.execIntentForm(user_reply, intent_form);
|
|
209
|
-
console.log("got form reply", form_reply)
|
|
210
|
-
//if (form_reply_message) {
|
|
211
|
-
if (!form_reply.canceled && form_reply.message) {
|
|
212
|
-
console.log("Form replying for next field...");
|
|
213
|
-
if (this.log) {console.log("Sending form reply...", form_reply.message)}
|
|
214
|
-
// reply with this message (ex. please enter your fullname)
|
|
215
|
-
if (!form_reply.message.attributes) {
|
|
216
|
-
form_reply.message.attributes = {}
|
|
217
|
-
}
|
|
218
|
-
form_reply.message.attributes.fillParams = true;
|
|
219
|
-
form_reply.message.attributes.splits = true;
|
|
220
|
-
form_reply.message.attributes.markbot = true;
|
|
221
|
-
return form_reply.message;
|
|
222
|
-
//apiext.sendSupportMessageExt(form_reply.message, projectId, requestId, token, () => {
|
|
223
|
-
// if (log) {console.log("FORM Message sent.", );}
|
|
224
|
-
//});
|
|
225
|
-
//return;
|
|
226
|
-
}
|
|
227
|
-
else if (form_reply.end) {
|
|
228
|
-
console.log("Form end.");
|
|
229
|
-
if (this.log) {console.log("unlocking intent for request", requestId);}
|
|
230
|
-
this.unlockIntent(requestId);
|
|
231
|
-
this.populatePrechatFormAndLead(message);
|
|
232
|
-
}
|
|
233
|
-
else if (form_reply.canceled) {
|
|
234
|
-
console.log("Form canceled.");
|
|
235
|
-
if (this.log) {console.log("unlocking intent due to canceling, for request", requestId);}
|
|
236
|
-
this.unlockIntent(requestId);
|
|
237
|
-
if (this.log) {console.log("sending form 'cancel' reply...", form_reply.message)}
|
|
238
|
-
// reply with this message (ex. please enter your fullname)
|
|
239
|
-
if (!form_reply.message.attributes) {
|
|
240
|
-
form_reply.message.attributes = {}
|
|
241
|
-
}
|
|
242
|
-
form_reply.message.attributes.fillParams = true;
|
|
243
|
-
form_reply.message.attributes.splits = true;
|
|
244
|
-
return form_reply.message
|
|
245
|
-
//apiext.sendSupportMessageExt(form_reply.message, projectId, requestId, token, () => {
|
|
246
|
-
// if (log) {console.log("FORM Message sent.", );}
|
|
247
|
-
//});
|
|
248
|
-
//return;
|
|
249
|
-
}
|
|
250
|
-
console.log("form_reply is", form_reply)
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// FORM END
|
|
254
|
-
|
|
255
|
-
const context = {
|
|
256
|
-
payload: {
|
|
257
|
-
botId: botId,
|
|
258
|
-
bot: bot,
|
|
259
|
-
message: message, // USER MESSAGE (JSON)
|
|
260
|
-
intent: answerObj
|
|
261
|
-
},
|
|
262
|
-
token: this.token
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
console.log("the static_bot_answer...")
|
|
266
|
-
const static_bot_answer = { // static design of the chatbot reply
|
|
267
|
-
//type: answerObj.type,
|
|
268
|
-
text: answerObj.answer,
|
|
269
|
-
attributes: answerObj.attributes,
|
|
270
|
-
metadata: answerObj.metadata,
|
|
271
|
-
// language: ?
|
|
272
|
-
// channel: ? whatsapp|telegram|facebook...
|
|
273
|
-
};
|
|
274
|
-
if (!static_bot_answer.attributes) {
|
|
275
|
-
static_bot_answer.attributes = {}
|
|
276
|
-
}
|
|
277
|
-
/*let attr = static_bot_answer.attributes;
|
|
278
|
-
if (!attr) {
|
|
279
|
-
attr = {};
|
|
280
|
-
}*/
|
|
281
|
-
var timestamp = Date.now();
|
|
282
|
-
static_bot_answer.attributes['clienttimestamp'] = timestamp;
|
|
283
|
-
if (answerObj && answerObj._id) {
|
|
284
|
-
static_bot_answer.attributes._answerid = answerObj._id.toString();
|
|
285
|
-
}
|
|
286
|
-
// DECORATES THE FINAL ANSWER
|
|
287
|
-
// question_payload = clone of user's original message
|
|
288
|
-
let question_payload = Object.assign({}, message);
|
|
289
|
-
delete question_payload.request;
|
|
290
|
-
let clonedfaqs = faqs.slice();
|
|
291
|
-
if (clonedfaqs && clonedfaqs.length > 0) {
|
|
292
|
-
clonedfaqs = clonedfaqs.shift()
|
|
293
|
-
}
|
|
294
|
-
const intent_info = {
|
|
295
|
-
intent_name: answerObj.intent_display_name,
|
|
296
|
-
is_fallback: false,
|
|
297
|
-
confidence: answerObj.score,
|
|
298
|
-
question_payload: question_payload,
|
|
299
|
-
others: clonedfaqs
|
|
300
|
-
}
|
|
301
|
-
static_bot_answer.attributes.intent_info = intent_info;
|
|
302
|
-
|
|
303
|
-
static_bot_answer.attributes.directives = true;
|
|
304
|
-
static_bot_answer.attributes.splits = true;
|
|
305
|
-
static_bot_answer.attributes.markbot = true;
|
|
306
|
-
static_bot_answer.attributes.fillParams = true;
|
|
307
|
-
static_bot_answer.attributes.webhook = answerObj.webhook_enabled;
|
|
308
|
-
|
|
309
|
-
// exec webhook (only)
|
|
310
|
-
const bot_answer = await this.execPipeline(static_bot_answer, message, bot, context, this.token);
|
|
311
|
-
|
|
312
|
-
//bot_answer.text = await fillWithRequestParams(bot_answer.text, requestId); // move to "ext" pipeline
|
|
313
|
-
console.log("returning answer", bot_answer)
|
|
314
|
-
return bot_answer;
|
|
315
|
-
|
|
316
|
-
/*apiext.sendSupportMessageExt(bot_answer, projectId, requestId, token, () => {
|
|
317
|
-
if (log) {console.log("Message sent");}
|
|
318
|
-
});*/
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
async lockIntent(requestId, intent_name) {
|
|
323
|
-
await this.tdcache.set("tilebot:requests:" + requestId + ":locked", intent_name);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
async currentLockedIntent(requestId) {
|
|
327
|
-
return await this.tdcache.get("tilebot:requests:" + requestId + ":locked");
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
async unlockIntent(requestId) {
|
|
331
|
-
await this.tdcache.del("tilebot:requests:" + ↩︎requestId + ":locked");
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
async addParameter(requestId, parameter_name, parameter_value) {
|
|
335
|
-
//await this.tdcache.hset("tilebot:requests:" + requestId + ":parameters", parameter_name, parameter_value);
|
|
336
|
-
await TiledeskChatbot.addParameterStatic(this.tdcache, requestId, parameter_name, parameter_value);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
static async addParameterStatic(_tdcache, requestId, parameter_name, parameter_value) {
|
|
340
|
-
await _tdcache.hset("tilebot:requests:" + requestId + ":parameters", parameter_name, parameter_value);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
async allParameters(requestId) {
|
|
344
|
-
//const parameters_key = "tilebot:requests:" + requestId + ":parameters";
|
|
345
|
-
//return await this.tdcache.hgetall(parameters_key);
|
|
346
|
-
return await TiledeskChatbot.allParametersStatic(this.tdcache, requestId);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
static async allParametersStatic(_tdcache, requestId) {
|
|
350
|
-
const parameters_key = "tilebot:requests:" + requestId + ":parameters";
|
|
351
|
-
return await _tdcache.hgetall(parameters_key);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
async execPipeline(static_bot_answer, message, bot, context) {
|
|
355
|
-
const messagePipeline = new MessagePipeline(static_bot_answer, context);
|
|
356
|
-
const webhookurl = bot.webhook_url;
|
|
357
|
-
messagePipeline.addPlug(new WebhookChatbotPlug(message.request, webhookurl, this.token));
|
|
358
|
-
//messagePipeline.addPlug(directivesPlug);
|
|
359
|
-
//messagePipeline.addPlug(new SplitsChatbotPlug(log));
|
|
360
|
-
//messagePipeline.addPlug(new MarkbotChatbotPlug(log));
|
|
361
|
-
const bot_answer = await messagePipeline.exec();
|
|
362
|
-
//if (log) {console.log("End pipeline, bot_answer:", JSON.stringify(bot_answer));}
|
|
363
|
-
return bot_answer;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
async execIntentForm(userInputReply, form) {
|
|
367
|
-
if (this.log) {console.log("executing intent form...")}
|
|
368
|
-
let intentForm = new IntentForm({form: form, requestId: this.requestId, chatbot: this, log: this.log});
|
|
369
|
-
let message = await intentForm.getMessage(userInputReply);
|
|
370
|
-
return message;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
async populatePrechatFormAndLead(message, callback) {
|
|
374
|
-
const tdclient = new TiledeskClient({
|
|
375
|
-
projectId: this.projectId,
|
|
376
|
-
token: this.token,
|
|
377
|
-
APIURL: this.APIURL,
|
|
378
|
-
APIKEY: this.APIKEY
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
const leadId = message.request.lead._id;
|
|
382
|
-
const requestId = message.request.request_id;
|
|
383
|
-
|
|
384
|
-
const parameters_key = "tilebot:requests:" + requestId + ":parameters";
|
|
385
|
-
const all_parameters = await this.tdcache.hgetall(parameters_key);
|
|
386
|
-
if (all_parameters) {
|
|
387
|
-
//console.log("all_parameters['userEmail']", all_parameters['userEmail'])
|
|
388
|
-
//console.log("all_parameters['userFullname']", all_parameters['userFullname']);
|
|
389
|
-
tdclient.updateLeadEmailFullname(leadId, null, all_parameters['userFullname'], () => {
|
|
390
|
-
if (this.log) {console.log("lead updated.")}
|
|
391
|
-
tdclient.updateRequestAttributes(requestId, {
|
|
392
|
-
preChatForm: all_parameters,
|
|
393
|
-
updated: Date.now
|
|
394
|
-
}, () => {
|
|
395
|
-
if (this.log) {console.log("prechat updated.");}
|
|
396
|
-
if (callback) {
|
|
397
|
-
callback();
|
|
398
|
-
}
|
|
399
|
-
});
|
|
400
|
-
});
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
module.exports = { TiledeskChatbot };
|