@tiledesk/tiledesk-tybot-connector 0.1.0
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/index.js +376 -0
- package/models/faq.js +120 -0
- package/models/faq_kb.js +87 -0
- package/package.json +28 -0
- package/publish.sh +10 -0
- package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +218 -0
- package/tiledeskChatbotPlugs/MarkbotChatbotPlug.js +85 -0
- package/tiledeskChatbotPlugs/MessagePipeline.js +116 -0
- package/tiledeskChatbotPlugs/SplitsChatbotPlug.js +48 -0
- package/tiledeskChatbotPlugs/WebhookChatbotPlug.js +182 -0
- package/tiledeskChatbotPlugs/package.json +27 -0
- package/tiledeskChatbotPlugs/publish.sh +10 -0
package/index.js
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const bodyParser = require('body-parser');
|
|
4
|
+
var cors = require('cors');
|
|
5
|
+
|
|
6
|
+
//router.use(cors());
|
|
7
|
+
router.use(bodyParser.json({limit: '50mb'}));
|
|
8
|
+
router.use(bodyParser.urlencoded({ extended: true , limit: '50mb'}));
|
|
9
|
+
|
|
10
|
+
// DEV
|
|
11
|
+
//const { MessagePipeline } = require('./tiledeskChatbotPlugs/MessagePipeline');
|
|
12
|
+
//const { DirectivesChatbotPlug } = require('./tiledeskChatbotPlugs/DirectivesChatbotPlug');
|
|
13
|
+
//const { SplitsChatbotPlug } = require('./tiledeskChatbotPlugs/SplitsChatbotPlug');
|
|
14
|
+
//const { MarkbotChatbotPlug } = require('./tiledeskChatbotPlugs/MarkbotChatbotPlug');
|
|
15
|
+
//const { WebhookChatbotPlug } = require('./tiledeskChatbotPlugs/WebhookChatbotPlug');
|
|
16
|
+
|
|
17
|
+
// PROD
|
|
18
|
+
const { MessagePipeline } = require('@tiledesk/tiledesk-chatbot-plugs/MessagePipeline');
|
|
19
|
+
const { DirectivesChatbotPlug } = require('@tiledesk/tiledesk-chatbot-plugs/DirectivesChatbotPlug');
|
|
20
|
+
const { SplitsChatbotPlug } = require('@tiledesk/tiledesk-chatbot-plugs/SplitsChatbotPlug');
|
|
21
|
+
const { MarkbotChatbotPlug } = require('@tiledesk/tiledesk-chatbot-plugs/MarkbotChatbotPlug');
|
|
22
|
+
const { WebhookChatbotPlug } = require('@tiledesk/tiledesk-chatbot-plugs/WebhookChatbotPlug');
|
|
23
|
+
|
|
24
|
+
var path = require("path");
|
|
25
|
+
var fs = require('fs');
|
|
26
|
+
|
|
27
|
+
const { TiledeskChatbotClient } = require('@tiledesk/tiledesk-chatbot-client');
|
|
28
|
+
const jwt = require('jsonwebtoken');
|
|
29
|
+
const { v4: uuidv4 } = require('uuid');
|
|
30
|
+
|
|
31
|
+
// THE IMPORT
|
|
32
|
+
var mongoose = require('mongoose');
|
|
33
|
+
var Faq = require('./models/faq');
|
|
34
|
+
var Faq_kb = require('./models/faq_kb');
|
|
35
|
+
let connection;
|
|
36
|
+
|
|
37
|
+
router.post('/ext/:botid', async (req, res) => {
|
|
38
|
+
console.log("Reques body:", req.body);
|
|
39
|
+
res.status(200).send({"success":true});
|
|
40
|
+
|
|
41
|
+
const botId = req.params.botid;
|
|
42
|
+
console.log("query botId:", botId);
|
|
43
|
+
const message = req.body.payload;
|
|
44
|
+
const faq_kb = req.body.hook;
|
|
45
|
+
const token = req.body.token;
|
|
46
|
+
|
|
47
|
+
//const bot = await Faq_kb.findById(botId).exec();
|
|
48
|
+
const bot = await Faq_kb.findById(botId).select('+secret').exec();
|
|
49
|
+
console.log("bot:", bot);
|
|
50
|
+
|
|
51
|
+
// CREATE TOKEN
|
|
52
|
+
//var botWithSecret = await Faq_kb.findById(bot._id).select('+secret').exec();
|
|
53
|
+
|
|
54
|
+
var signOptions = {
|
|
55
|
+
issuer: 'https://tiledesk.com',
|
|
56
|
+
subject: 'bot',
|
|
57
|
+
audience: 'https://tiledesk.com/bots/'+bot._id,
|
|
58
|
+
jwtid: uuidv4()
|
|
59
|
+
};
|
|
60
|
+
const bot_token = jwt.sign(bot.toObject(), bot.secret, signOptions);
|
|
61
|
+
console.log("bot_token:", bot_token);
|
|
62
|
+
//
|
|
63
|
+
|
|
64
|
+
// SETUP EXACT MATCH
|
|
65
|
+
let query = { "id_project": message.id_project, "id_faq_kb": botId, "question": message.text };
|
|
66
|
+
// BUT CHECKING ACTION BUTTON...
|
|
67
|
+
if (message.attributes && message.attributes.action) {
|
|
68
|
+
var action = message.attributes.action;
|
|
69
|
+
var action_parameters_index = action.indexOf("?");
|
|
70
|
+
if (action_parameters_index > -1) {
|
|
71
|
+
action = action.substring(0, action_parameters_index);
|
|
72
|
+
}
|
|
73
|
+
console.debug("action: " + action);
|
|
74
|
+
query = { "id_project": message.id_project, "id_faq_kb": botId, "intent_display_name": action };
|
|
75
|
+
//var isObjectId = mongoose.Types.ObjectId.isValid(action);
|
|
76
|
+
//console.debug("isObjectId:" + isObjectId);
|
|
77
|
+
//if (isObjectId) {
|
|
78
|
+
// query = { "id_project": message.id_project, "id_faq_kb": botId, "_id": action };
|
|
79
|
+
//} else {
|
|
80
|
+
// query = { "id_project": message.id_project, "id_faq_kb": botId, $or: [{ "intent_id": action }, { "intent_display_name": action }] };
|
|
81
|
+
//}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// SEARCH INTENTS
|
|
85
|
+
Faq.find(query).lean().exec(async (err, faqs) => {
|
|
86
|
+
if (err) {
|
|
87
|
+
return console.error("Error getting faq object.", err);
|
|
88
|
+
}
|
|
89
|
+
if (faqs && faqs.length > 0 && faqs[0].answer) { // EXACT MATCH!
|
|
90
|
+
console.log("FAQ:", faqs[0]);
|
|
91
|
+
execFaq(req, res, faqs, botId, message, bot_token, bot);
|
|
92
|
+
}
|
|
93
|
+
else { // FULL TEXT
|
|
94
|
+
console.log("Go fulltext...");
|
|
95
|
+
query = { "id_project": message.id_project, "id_faq_kb": botId };
|
|
96
|
+
var mongoproject = undefined;
|
|
97
|
+
var sort = undefined;
|
|
98
|
+
var search_obj = { "$search": message.text };
|
|
99
|
+
|
|
100
|
+
if (faq_kb.language) {
|
|
101
|
+
search_obj["$language"] = faq_kb.language;
|
|
102
|
+
}
|
|
103
|
+
query.$text = search_obj;
|
|
104
|
+
console.debug("fulltext search query", query);
|
|
105
|
+
|
|
106
|
+
mongoproject = { score: { $meta: "textScore" } };
|
|
107
|
+
sort = { score: { $meta: "textScore" } }
|
|
108
|
+
// DA QUI RECUPERO LA RISPOSTA DATO (ID: SE EXT_AI) (QUERY FULLTEXT SE NATIVE-BASIC-AI)
|
|
109
|
+
Faq.find(query, mongoproject).sort(sort).lean().exec(async (err, faqs) => {
|
|
110
|
+
console.log("Found:", faqs);
|
|
111
|
+
if (err) {
|
|
112
|
+
console.erro("Error:", err);
|
|
113
|
+
return console.error('Error getting fulltext objects.', err);
|
|
114
|
+
}
|
|
115
|
+
console.debug("faqs:", faqs);
|
|
116
|
+
if (faqs && faqs.length > 0 && faqs[0].answer) {
|
|
117
|
+
execFaq(req, res, faqs, botId, message, bot_token, bot);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
// fallback
|
|
121
|
+
const fallbackIntent = await getIntentByDisplayName("defaultFallback", bot);
|
|
122
|
+
const faqs = [fallbackIntent];
|
|
123
|
+
execFaq(req, res, faqs, botId, message, bot_token, bot);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
async function execFaq(req, res, faqs, botId, message, token, bot) {
|
|
132
|
+
let sender = 'bot_' + botId;
|
|
133
|
+
console.debug("sender", sender);
|
|
134
|
+
var answerObj;
|
|
135
|
+
answerObj = faqs[0];
|
|
136
|
+
answerObj.score = 100; //exact search not set score
|
|
137
|
+
console.debug("answerObj.score", answerObj.score);
|
|
138
|
+
|
|
139
|
+
const context = {
|
|
140
|
+
payload: {
|
|
141
|
+
//text: text,
|
|
142
|
+
bot: bot,
|
|
143
|
+
message: message, // USER MESSAGE (JSON)
|
|
144
|
+
intent: answerObj
|
|
145
|
+
},
|
|
146
|
+
token: token
|
|
147
|
+
};
|
|
148
|
+
const static_bot_answer = { // static design of the chatbot reply
|
|
149
|
+
//type: answerObj.type,
|
|
150
|
+
text: answerObj.answer,
|
|
151
|
+
attributes: answerObj.attributes,
|
|
152
|
+
metadata: answerObj.metadata,
|
|
153
|
+
// language: ?
|
|
154
|
+
// channel: ? whatsapp|telegram|facebook...
|
|
155
|
+
};
|
|
156
|
+
if (!static_bot_answer.attributes) {
|
|
157
|
+
static_bot_answer.attributes = {}
|
|
158
|
+
}
|
|
159
|
+
static_bot_answer.attributes.directives = true;
|
|
160
|
+
static_bot_answer.attributes.splits = false;
|
|
161
|
+
static_bot_answer.attributes.markbot = true;
|
|
162
|
+
|
|
163
|
+
static_bot_answer.attributes.webhook = answerObj.webhook_enabled;
|
|
164
|
+
console.log("static_bot_answer.attributes", static_bot_answer.attributes)
|
|
165
|
+
|
|
166
|
+
// faq[0] => PIPELINE => bot_answer
|
|
167
|
+
const APIURL = "https://tiledesk-server-pre.herokuapp.com"
|
|
168
|
+
const messagePipeline = new MessagePipeline(static_bot_answer, context);
|
|
169
|
+
const webhookurl = bot.webhook_url;
|
|
170
|
+
messagePipeline.addPlug(new WebhookChatbotPlug(message.request, webhookurl, token));
|
|
171
|
+
let directivesPlug = new DirectivesChatbotPlug(message.request, APIURL, token);
|
|
172
|
+
messagePipeline.addPlug(directivesPlug);
|
|
173
|
+
messagePipeline.addPlug(new SplitsChatbotPlug());
|
|
174
|
+
messagePipeline.addPlug(new MarkbotChatbotPlug());
|
|
175
|
+
const bot_answer = await messagePipeline.exec();
|
|
176
|
+
console.log("End pipeline, bot_answer:", JSON.stringify(bot_answer));
|
|
177
|
+
|
|
178
|
+
var attr = bot_answer.attributes;
|
|
179
|
+
if (!attr) {
|
|
180
|
+
attr = {};
|
|
181
|
+
}
|
|
182
|
+
var timestamp = Date.now();
|
|
183
|
+
attr['clienttimestamp'] = timestamp;
|
|
184
|
+
if (answerObj && answerObj._id) {
|
|
185
|
+
attr._answerid = answerObj._id.toString();
|
|
186
|
+
}
|
|
187
|
+
// DECORATES THE FINAL ANSWER
|
|
188
|
+
// question_payload = clone of user's original message
|
|
189
|
+
let question_payload = Object.assign({}, message);
|
|
190
|
+
delete question_payload.request;
|
|
191
|
+
let clonedfaqs = faqs.slice();
|
|
192
|
+
if (clonedfaqs && clonedfaqs.length > 0) {
|
|
193
|
+
clonedfaqs = clonedfaqs.shift()
|
|
194
|
+
}
|
|
195
|
+
const intent_info = {
|
|
196
|
+
intent_name: answerObj.intent_display_name,
|
|
197
|
+
is_fallback: false,
|
|
198
|
+
confidence: answerObj.score,
|
|
199
|
+
question_payload: question_payload,
|
|
200
|
+
others: clonedfaqs
|
|
201
|
+
}
|
|
202
|
+
console.debug("intent_info", intent_info);
|
|
203
|
+
attr.intent_info = intent_info;
|
|
204
|
+
const tdclient = new TiledeskChatbotClient(
|
|
205
|
+
{
|
|
206
|
+
request: req,
|
|
207
|
+
APIKEY: '__APIKEY__',
|
|
208
|
+
APIURL: APIURL
|
|
209
|
+
});
|
|
210
|
+
console.log("Sending back:", JSON.stringify(bot_answer));
|
|
211
|
+
tdclient.sendMessage(bot_answer, () => {
|
|
212
|
+
console.log("Message sent.");
|
|
213
|
+
directivesPlug.processDirectives(() => {
|
|
214
|
+
console.log("End processing directives.");
|
|
215
|
+
})
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function getIntentByDisplayName(name, bot) {
|
|
220
|
+
return new Promise(function(resolve, reject) {
|
|
221
|
+
var query = { "id_project": bot.id_project, "id_faq_kb": bot._id, "intent_display_name": name};
|
|
222
|
+
console.debug('query', query);
|
|
223
|
+
Faq.find(query).lean().exec(function (err, faqs) {
|
|
224
|
+
if (err) {
|
|
225
|
+
return reject();
|
|
226
|
+
}
|
|
227
|
+
console.debug("faqs", faqs);
|
|
228
|
+
if (faqs && faqs.length > 0) {
|
|
229
|
+
const intent = faqs[0];
|
|
230
|
+
return resolve(intent);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
return resolve(null);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// IGNORALA
|
|
240
|
+
/*app.post('/extorig', (req, res) => {
|
|
241
|
+
res.status(200).send({"success":true});
|
|
242
|
+
const tdclient =
|
|
243
|
+
new TiledeskChatbotClient(
|
|
244
|
+
{
|
|
245
|
+
APIURL: apiurl(),
|
|
246
|
+
request: req,
|
|
247
|
+
APIKEY: '__APIKEY__'
|
|
248
|
+
});
|
|
249
|
+
if (tdclient.text === "\\start") {
|
|
250
|
+
tdclient.sendMessage(
|
|
251
|
+
{
|
|
252
|
+
text: 'started',
|
|
253
|
+
attributes: {
|
|
254
|
+
attachment: {
|
|
255
|
+
type:"template",
|
|
256
|
+
buttons: [
|
|
257
|
+
{
|
|
258
|
+
type: "text",
|
|
259
|
+
value: "Ok"
|
|
260
|
+
}
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
tdclient.sendMessage({text: 'Not trained for this'});
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
*/
|
|
272
|
+
|
|
273
|
+
// Tiledesk Resolution-bot webhook endpoint
|
|
274
|
+
/*app.post('/bot', async (req, res) => {
|
|
275
|
+
console.log("Webhook. Request body: " + JSON.stringify(req.body));
|
|
276
|
+
// INTENTS
|
|
277
|
+
let intent = null;
|
|
278
|
+
intent = req.body.payload.intent.intent_display_name;
|
|
279
|
+
//const projectId = req.body.payload.bot.id_project;
|
|
280
|
+
const token = req.body.token;
|
|
281
|
+
const request = req.body.payload.message.request;
|
|
282
|
+
//const requestId = request.request_id;
|
|
283
|
+
console.log("Got intent:", intent);
|
|
284
|
+
API_URL = apiurl();
|
|
285
|
+
const original_answer = req.body.payload.intent.answer;
|
|
286
|
+
|
|
287
|
+
const messagePipeline = new MessagePipeline();
|
|
288
|
+
messagePipeline.addPlug(new DirectivesChatbotPlug(request, API_URL, token));
|
|
289
|
+
messagePipeline.addPlug(new SplitsChatbotPlug());
|
|
290
|
+
messagePipeline.addPlug(new MarkbotChatbotPlug());
|
|
291
|
+
|
|
292
|
+
const message = {
|
|
293
|
+
text: original_answer
|
|
294
|
+
};
|
|
295
|
+
messagePipeline.execOn(message, (_message) => {
|
|
296
|
+
res.json(_message);
|
|
297
|
+
console.log("End pipeline.");
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
});*/
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
function apiurl() {
|
|
307
|
+
const server = "pre";
|
|
308
|
+
//const server = "prod";
|
|
309
|
+
const API_URL_PRE = 'https://tiledesk-server-pre.herokuapp.com';
|
|
310
|
+
const API_URL_PROD = 'https://api.tiledesk.com/v2';
|
|
311
|
+
// choose a server
|
|
312
|
+
let API_URL = API_URL_PROD;
|
|
313
|
+
if (server === 'pre') {
|
|
314
|
+
API_URL = API_URL_PRE;
|
|
315
|
+
}
|
|
316
|
+
return API_URL;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
router.get('/', (req, res) => {
|
|
321
|
+
res.send('Hello Tybot!');
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
function startTybot(settings, completionCallback) {
|
|
325
|
+
console.log("Starting Tybot with Settings:", settings);
|
|
326
|
+
|
|
327
|
+
if (!settings.MONGODB_URI) {
|
|
328
|
+
throw new Error("settings.MONGODB_URI is mandatory.");
|
|
329
|
+
}
|
|
330
|
+
if (!settings.API_ENDPOINT) {
|
|
331
|
+
throw new Error("settings.API_ENDPOINT is mandatory.");
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
API_ENDPOINT = settings.API_ENDPOINT;
|
|
335
|
+
console.log("(Tybot) settings.API_ENDPOINT:", API_ENDPOINT);
|
|
336
|
+
}
|
|
337
|
+
if (!settings.log) {
|
|
338
|
+
log = false;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
console.log("Starting Tybot connector...");
|
|
342
|
+
console.log("(Tybot) Connecting to mongodb...");
|
|
343
|
+
|
|
344
|
+
connection = mongoose.connect(process.env.mongoUrl, { "useNewUrlParser": true, "autoIndex": false }, function(err) {
|
|
345
|
+
if (err) {
|
|
346
|
+
console.error('Failed to connect to MongoDB on ' + settings.MONGODB_URI + " ", err);
|
|
347
|
+
//process.exit(1); // add => exitOnFail: true
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
console.info("Tybot Mongodb connected.");
|
|
351
|
+
if (completionCallback) {
|
|
352
|
+
completionCallback();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/*
|
|
359
|
+
var connection = mongoose.connect(process.env.mongoUrl, { "useNewUrlParser": true, "autoIndex": false }, function(err) {
|
|
360
|
+
if (err) {
|
|
361
|
+
console.error('Failed to connect to MongoDB on ' + process.env.mongoUrl + " ", err);
|
|
362
|
+
//process.exit(1);
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
console.info("Mongodb connected")
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
*/
|
|
369
|
+
|
|
370
|
+
/*
|
|
371
|
+
app.listen(3000, () => {
|
|
372
|
+
console.log('server started');
|
|
373
|
+
});
|
|
374
|
+
*/
|
|
375
|
+
|
|
376
|
+
module.exports = { router: router, startTybot: startTybot};
|
package/models/faq.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
var mongoose = require('mongoose');
|
|
2
|
+
var Schema = mongoose.Schema;
|
|
3
|
+
var { nanoid } = require("nanoid");
|
|
4
|
+
const uuidv4 = require('uuid/v4');
|
|
5
|
+
|
|
6
|
+
var defaultFullTextLanguage = process.env.DEFAULT_FULLTEXT_INDEX_LANGUAGE || "none";
|
|
7
|
+
|
|
8
|
+
var FaqSchema = new Schema({
|
|
9
|
+
id_faq_kb: {
|
|
10
|
+
type: String,
|
|
11
|
+
index: true
|
|
12
|
+
},
|
|
13
|
+
intent_id: {
|
|
14
|
+
type: String,
|
|
15
|
+
required: false,
|
|
16
|
+
index:true,
|
|
17
|
+
default: function() {
|
|
18
|
+
return uuidv4();
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
intent_display_name: { //documentare
|
|
22
|
+
type: String,
|
|
23
|
+
required: false,
|
|
24
|
+
index:true,
|
|
25
|
+
default: function() {
|
|
26
|
+
return nanoid(6);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
question: {
|
|
30
|
+
type: String,
|
|
31
|
+
required: true
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
webhook_enabled: { //usa questo
|
|
35
|
+
type: Boolean,
|
|
36
|
+
required: false,
|
|
37
|
+
default: false,
|
|
38
|
+
},
|
|
39
|
+
answer: {
|
|
40
|
+
type: String,
|
|
41
|
+
required: true
|
|
42
|
+
},
|
|
43
|
+
id_project: {
|
|
44
|
+
type: String,
|
|
45
|
+
required: true,
|
|
46
|
+
index: true
|
|
47
|
+
},
|
|
48
|
+
topic: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: "default",
|
|
51
|
+
index: true
|
|
52
|
+
// required: true
|
|
53
|
+
},
|
|
54
|
+
status: {
|
|
55
|
+
type: String,
|
|
56
|
+
default: "live",
|
|
57
|
+
index: true
|
|
58
|
+
// required: true
|
|
59
|
+
},
|
|
60
|
+
language: {
|
|
61
|
+
type: String,
|
|
62
|
+
required: false,
|
|
63
|
+
index: true
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
// "stats":{
|
|
67
|
+
// "conversation_count":2,
|
|
68
|
+
// "all_done_count":0,
|
|
69
|
+
// "wait_for_team_count":2
|
|
70
|
+
// }
|
|
71
|
+
|
|
72
|
+
createdBy: {
|
|
73
|
+
type: String,
|
|
74
|
+
required: true
|
|
75
|
+
}
|
|
76
|
+
},{
|
|
77
|
+
timestamps: true,
|
|
78
|
+
toJSON: { virtuals: true } //used to polulate messages in toJSON// https://mongoosejs.com/docs/populate.html
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
FaqSchema.virtual('faq_kb', {
|
|
83
|
+
ref: 'faq_kb', // The model to use
|
|
84
|
+
localField: 'id_faq_kb', // Find people where `localField`
|
|
85
|
+
foreignField: '_id', // is equal to `foreignField`
|
|
86
|
+
justOne: false,
|
|
87
|
+
//options: { sort: { name: -1 }, limit: 5 } // Query options, see http://bit.ly/mongoose-query-options
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
FaqSchema.index({ id_project: 1, id_faq_kb: 1, question: 1 });
|
|
91
|
+
|
|
92
|
+
// https://docs.mongodb.com/manual/core/index-text/
|
|
93
|
+
// https://docs.mongodb.com/manual/tutorial/specify-language-for-text-index/
|
|
94
|
+
// https://docs.mongodb.com/manual/reference/text-search-languages/#text-search-languages
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
FaqSchema.index({question: 'text'},
|
|
98
|
+
{"name":"faq_fulltext","default_language": defaultFullTextLanguage,"language_override": "language"}); // schema level
|
|
99
|
+
|
|
100
|
+
// FaqSchema.index({question: 'text', answer: 'text'},
|
|
101
|
+
// {"name":"faq_fulltext","default_language": defaultFullTextLanguage,"language_override": "language", weights: {question: 10,answer: 1}}); // schema level
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
FaqSchema.index({ id_project: 1, id_faq_kb: 1, intent_display_name: 1 }, { unique: true });
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
var faq = mongoose.model('faq', FaqSchema);
|
|
108
|
+
|
|
109
|
+
//faq.on('index', function(error) {
|
|
110
|
+
// "_id index cannot be sparse"
|
|
111
|
+
//console.debug('index:', error);
|
|
112
|
+
//});
|
|
113
|
+
|
|
114
|
+
if (process.env.MONGOOSE_SYNCINDEX) {
|
|
115
|
+
faq.syncIndexes();
|
|
116
|
+
console.info("faq syncIndexes")
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
module.exports = faq;
|
package/models/faq_kb.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
var mongoose = require('mongoose');
|
|
2
|
+
var Schema = mongoose.Schema;
|
|
3
|
+
const uuidv4 = require('uuid/v4');
|
|
4
|
+
|
|
5
|
+
var Faq_kbSchema = new Schema({
|
|
6
|
+
name: {
|
|
7
|
+
type: String,
|
|
8
|
+
required: true,
|
|
9
|
+
index:true
|
|
10
|
+
},
|
|
11
|
+
description: {
|
|
12
|
+
type: String,
|
|
13
|
+
// index:true
|
|
14
|
+
},
|
|
15
|
+
url: {
|
|
16
|
+
type: String,
|
|
17
|
+
// required: true
|
|
18
|
+
},
|
|
19
|
+
webhook_url: {
|
|
20
|
+
type: String,
|
|
21
|
+
// required: true
|
|
22
|
+
},
|
|
23
|
+
webhook_enabled: {
|
|
24
|
+
type: Boolean,
|
|
25
|
+
required: false,
|
|
26
|
+
default: false,
|
|
27
|
+
},
|
|
28
|
+
id_project: {
|
|
29
|
+
type: String,
|
|
30
|
+
required: true,
|
|
31
|
+
index: true
|
|
32
|
+
},
|
|
33
|
+
// kbkey_remote: { //serve?
|
|
34
|
+
// type: String,
|
|
35
|
+
// },
|
|
36
|
+
type: {
|
|
37
|
+
type: String,
|
|
38
|
+
default: 'internal',
|
|
39
|
+
index: true
|
|
40
|
+
},
|
|
41
|
+
// external: {
|
|
42
|
+
// type: Boolean,
|
|
43
|
+
// default: false
|
|
44
|
+
// },
|
|
45
|
+
trashed: {
|
|
46
|
+
type: Boolean,
|
|
47
|
+
index: true
|
|
48
|
+
},
|
|
49
|
+
secret: {
|
|
50
|
+
type: String,
|
|
51
|
+
required: true,
|
|
52
|
+
default: uuidv4(),
|
|
53
|
+
select: false
|
|
54
|
+
},
|
|
55
|
+
language: {
|
|
56
|
+
type: String,
|
|
57
|
+
required: false,
|
|
58
|
+
default: 'en'
|
|
59
|
+
// index: true
|
|
60
|
+
},
|
|
61
|
+
attributes: {
|
|
62
|
+
type: Object,
|
|
63
|
+
},
|
|
64
|
+
createdBy: {
|
|
65
|
+
type: String,
|
|
66
|
+
required: true
|
|
67
|
+
}
|
|
68
|
+
},{
|
|
69
|
+
timestamps: true
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
Faq_kbSchema.virtual('fullName').get(function () {
|
|
74
|
+
// winston.debug("faq_kb fullName virtual called");
|
|
75
|
+
return (this.name);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
var faq_kb = mongoose.model('faq_kb', Faq_kbSchema);
|
|
79
|
+
|
|
80
|
+
if (process.env.MONGOOSE_SYNCINDEX) {
|
|
81
|
+
faq_kb.syncIndexes();
|
|
82
|
+
console.log("faq_kb syncIndexes");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
module.exports = faq_kb
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tiledesk/tiledesk-tybot-connector",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Tiledesk Tybot connector",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"start": "node index.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@tiledesk/tiledesk-chatbot-client": "^0.5.30",
|
|
15
|
+
"@tiledesk/tiledesk-chatbot-util": "^0.8.36",
|
|
16
|
+
"@tiledesk/tiledesk-client": "^0.8.28",
|
|
17
|
+
"@tiledesk/tiledesk-chatbot-plugs": "^0.1.1",
|
|
18
|
+
"axios": "^0.27.2",
|
|
19
|
+
"body-parser": "^1.19.0",
|
|
20
|
+
"express": "^4.17.1",
|
|
21
|
+
"jsonwebtoken": "^8.5.1",
|
|
22
|
+
"mongoose": "^6.3.5",
|
|
23
|
+
"nanoid": "^3.1.25",
|
|
24
|
+
"request": "^2.88.2",
|
|
25
|
+
"uuid": "^3.3.3",
|
|
26
|
+
"cors": "^2.8.5"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/publish.sh
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#npm version patch
|
|
2
|
+
version=`node -e 'console.log(require("./package.json").version)'`
|
|
3
|
+
echo "version $version"
|
|
4
|
+
|
|
5
|
+
if [ "$version" != "" ]; then
|
|
6
|
+
git tag -a "$version" -m "`git log -1 --format=%s`"
|
|
7
|
+
echo "Created a new tag, $version"
|
|
8
|
+
git push --tags
|
|
9
|
+
npm publish --access public
|
|
10
|
+
fi
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
const { TiledeskChatbotUtil } = require('@tiledesk/tiledesk-chatbot-util');
|
|
2
|
+
const { TiledeskClient } = require('@tiledesk/tiledesk-client');
|
|
3
|
+
|
|
4
|
+
class DirectivesChatbotPlug {
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @example
|
|
8
|
+
* const { DirectivesChatbotPlug } = require('./DirectivesChatbotPlug');
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
constructor(supportRequest, API_URL, token) {
|
|
13
|
+
this.supportRequest = supportRequest;
|
|
14
|
+
this.API_URL = API_URL;
|
|
15
|
+
this.token = token;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
exec(pipeline) {
|
|
19
|
+
let message = pipeline.message;
|
|
20
|
+
if (message.attributes && message.attributes.directives && message.attributes.directives == true) {
|
|
21
|
+
const message_text = message.text;
|
|
22
|
+
console.log("processing message:", message_text);
|
|
23
|
+
/*const message_text =
|
|
24
|
+
`We are looking for an operator..
|
|
25
|
+
-
|
|
26
|
+
JUST WAIT A MOMENT
|
|
27
|
+
\\agent`;*/
|
|
28
|
+
let parsed_result = TiledeskChatbotUtil.parseDirectives(message_text);
|
|
29
|
+
console.log("Message directives:", parsed_result);
|
|
30
|
+
console.log("Message text ripped from directives:", parsed_result.text);
|
|
31
|
+
if (parsed_result && parsed_result.directives && parsed_result.directives.length > 0) {
|
|
32
|
+
// do not process more intents. Process directives and return
|
|
33
|
+
const text = parsed_result.text;
|
|
34
|
+
message.text = text;
|
|
35
|
+
this.directives = parsed_result.directives;
|
|
36
|
+
pipeline.nextplug();
|
|
37
|
+
/*this.processDirectives( () => {
|
|
38
|
+
console.log("End process directives.");
|
|
39
|
+
pipeline.nextplug();
|
|
40
|
+
});*/
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
pipeline.nextplug();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
pipeline.nextplug();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
moveToDepartment(tdclient, requestId, depName, callback) {
|
|
56
|
+
tdclient.getAllDepartments((err, deps) => {
|
|
57
|
+
console.log("deps:", deps, err);
|
|
58
|
+
if (err) {
|
|
59
|
+
console.error("getAllDepartments() error:", err);
|
|
60
|
+
callback(err);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
let dep = null;
|
|
64
|
+
for(i=0; i < deps.length; i++) {
|
|
65
|
+
d = deps[i];
|
|
66
|
+
if (d.name.toLowerCase() === depName.toLowerCase()) {
|
|
67
|
+
dep = d;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (dep) {
|
|
72
|
+
tdclient.updateRequestDepartment(requestId, dep._id, null, (err) => {
|
|
73
|
+
if (err) {
|
|
74
|
+
console.error("An error:", err);
|
|
75
|
+
callback(err);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
callback();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
processDirectives(theend) {
|
|
86
|
+
|
|
87
|
+
const directives = this.directives;
|
|
88
|
+
if (!directives || directives.length === 0) {
|
|
89
|
+
console.log("No directives to process.");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const supportRequest = this.supportRequest;
|
|
93
|
+
const token = this.token;
|
|
94
|
+
const API_URL = this.API_URL;
|
|
95
|
+
|
|
96
|
+
const requestId = supportRequest.request_id
|
|
97
|
+
const depId = supportRequest.department._id;
|
|
98
|
+
const projectId = supportRequest.id_project;
|
|
99
|
+
const tdclient = new TiledeskClient({
|
|
100
|
+
projectId: projectId,
|
|
101
|
+
token: token,
|
|
102
|
+
APIURL: API_URL,
|
|
103
|
+
APIKEY: "___",
|
|
104
|
+
log:false
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
let i = -1;
|
|
108
|
+
console.log("processing directives:", directives);
|
|
109
|
+
function process(directive) {
|
|
110
|
+
if (directive) {
|
|
111
|
+
console.log("directive:", directive);
|
|
112
|
+
console.log("directive.name:", directive.name);
|
|
113
|
+
}
|
|
114
|
+
let directive_name = null;
|
|
115
|
+
if (directive && directive.name) {
|
|
116
|
+
directive_name = directive.name.toLowerCase();
|
|
117
|
+
}
|
|
118
|
+
if (directive == null) {
|
|
119
|
+
theend();
|
|
120
|
+
}
|
|
121
|
+
else if (directive_name === TiledeskChatbotUtil.DEPARTMENT_DIRECTIVE) {
|
|
122
|
+
let dep_name = "default department";
|
|
123
|
+
if (directive.parameter) {
|
|
124
|
+
dep_name = directive.parameter;
|
|
125
|
+
}
|
|
126
|
+
console.log("department:", dep_name);
|
|
127
|
+
moveToDepartment(tdclient, requestId, dep_name, () => {
|
|
128
|
+
console.log("moved to department:", dep_name);
|
|
129
|
+
process(nextDirective());
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else if (directive_name === TiledeskChatbotUtil.HMESSAGE_DIRECTIVE) {
|
|
133
|
+
if (directive.parameter) {
|
|
134
|
+
let text = directive.parameter.trim();
|
|
135
|
+
let message = {
|
|
136
|
+
text: text,
|
|
137
|
+
attributes: {
|
|
138
|
+
subtype: "info"
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
console.log("Message:", message)
|
|
142
|
+
tdclient.sendSupportMessage(requestId, message, () => {
|
|
143
|
+
process(nextDirective());
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (directive_name === TiledeskChatbotUtil.MESSAGE_DIRECTIVE) {
|
|
148
|
+
if (directive.parameter) {
|
|
149
|
+
let text = directive.parameter.trim();
|
|
150
|
+
let message = {text: text};
|
|
151
|
+
console.log("text.lastIndexOf(hide)", text.lastIndexOf("\\hide"))
|
|
152
|
+
if (text.lastIndexOf("\\hide") >= 0) {
|
|
153
|
+
console.log("HIDDEN");
|
|
154
|
+
message.text = text.slice(0, text.lastIndexOf("\\hide")).trim();
|
|
155
|
+
message.attributes = {
|
|
156
|
+
subtype: "info"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
console.log("Message:", message)
|
|
160
|
+
tdclient.sendSupportMessage(requestId, message, () => {
|
|
161
|
+
process(nextDirective());
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else if (directive_name === "\\agent") {
|
|
166
|
+
console.log("assign to request:", requestId);
|
|
167
|
+
console.log("assign to dep:", depId);
|
|
168
|
+
console.log("assign to dep name:", supportRequest.department.name);
|
|
169
|
+
tdclient.log = true;
|
|
170
|
+
tdclient.agent(requestId, depId, (err) => {
|
|
171
|
+
if (err) {
|
|
172
|
+
console.error("Error moving to agent:", err);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
console.log("Successfully moved to agent");
|
|
176
|
+
}
|
|
177
|
+
process(nextDirective());
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
else if (directive_name === "\\removecurrentbot") {
|
|
181
|
+
console.log("assign to request:", requestId);
|
|
182
|
+
console.log("assign to dep:", depId);
|
|
183
|
+
console.log("assign to dep name:", request.department.name);
|
|
184
|
+
tdclient.log = true;
|
|
185
|
+
tdclient.removeCurrentBot(requestId, (err) => {
|
|
186
|
+
if (err) {
|
|
187
|
+
console.error("Error removeCurrentBot():", err);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
console.log("Successfully removeCurrentBot()");
|
|
191
|
+
}
|
|
192
|
+
process(nextDirective());
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
console.log("Unknown directive:", directive.name);
|
|
197
|
+
process(nextDirective());
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
process(nextDirective());
|
|
201
|
+
|
|
202
|
+
function nextDirective() {
|
|
203
|
+
i += 1;
|
|
204
|
+
console.log("i:", i);
|
|
205
|
+
if (i < directives.length) {
|
|
206
|
+
let nextd = directives[i];
|
|
207
|
+
console.log("next:", nextd);
|
|
208
|
+
return nextd;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
module.exports = { DirectivesChatbotPlug };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const { TiledeskChatbotUtil } = require('@tiledesk/tiledesk-chatbot-util');
|
|
2
|
+
|
|
3
|
+
class MarkbotChatbotPlug {
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @example
|
|
8
|
+
* const { MarkbotChatbotPlug } = require('./MarkbotChatbotPlug');
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
constructor() {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exec(pipeline) {
|
|
16
|
+
let message = pipeline.message;
|
|
17
|
+
console.log("markbot, message.attributes", message.attributes)
|
|
18
|
+
if (message.attributes && message.attributes.markbot != undefined && message.attributes.markbot == false) {
|
|
19
|
+
console.log("markbot disabled")
|
|
20
|
+
pipeline.nextplug();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// the legacy 'microlanguage' command
|
|
24
|
+
/*if (message.attributes && message.attributes.microlanguage != undefined && message.attributes.microlanguage == false) {
|
|
25
|
+
console.log("microlanguage disabled");
|
|
26
|
+
pipeline.nextplug();
|
|
27
|
+
return;
|
|
28
|
+
}*/
|
|
29
|
+
|
|
30
|
+
if (!message.attributes) {
|
|
31
|
+
message.attributes = {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (message.text) {
|
|
35
|
+
console.log("markbotting main message...");
|
|
36
|
+
let parsed_reply = TiledeskChatbotUtil.parseReply(message.text);
|
|
37
|
+
console.log("parsed", JSON.stringify(parsed_reply));
|
|
38
|
+
if (parsed_reply) {
|
|
39
|
+
message.text = parsed_reply.message.text;
|
|
40
|
+
message.type = parsed_reply.message.type;
|
|
41
|
+
message.metadata = parsed_reply.message.metadata;
|
|
42
|
+
console.log("parsed_reply.message.attributes", parsed_reply.message.attributes);
|
|
43
|
+
if (parsed_reply.message.attributes) {
|
|
44
|
+
for(const [key, value] of Object.entries(parsed_reply.message.attributes)) {
|
|
45
|
+
console.log("key:", key)
|
|
46
|
+
console.log("value:", value)
|
|
47
|
+
|
|
48
|
+
message.attributes[key] = value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//message.attributes.attachment = parsed_reply.message.attributes.attachment;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (message.attributes && message.attributes.commands) {
|
|
56
|
+
let commands = message.attributes.commands;
|
|
57
|
+
console.log("commands for markbot:", commands);
|
|
58
|
+
if (commands.length > 1) {
|
|
59
|
+
for (let i = 0; i < commands.length; i++) {
|
|
60
|
+
if (commands[i].type === 'message' && commands[i].message && commands[i].message.text) {
|
|
61
|
+
let parsed_reply = TiledeskChatbotUtil.parseReply(commands[i].message.text);
|
|
62
|
+
//console.log("PARSED***", parsed_reply);
|
|
63
|
+
commands[i].message = parsed_reply.message;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
console.log("Message out of Markbot:", JSON.stringify(message));
|
|
69
|
+
pipeline.nextplug(pipeline);
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
next(pipeline, completionCallback) {
|
|
75
|
+
const plug = pipeline.nextplug();
|
|
76
|
+
if (!plug) {
|
|
77
|
+
completionCallback();
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
plug.exec(pipeline);
|
|
81
|
+
}
|
|
82
|
+
}*/
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = { MarkbotChatbotPlug };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
class MessagePipeline {
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @example
|
|
5
|
+
* const { MessagePipeline } = require('./MessagePipeline');
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
constructor(message, context) {
|
|
10
|
+
this.context = context;
|
|
11
|
+
this.message = message;
|
|
12
|
+
this.plugs = [];
|
|
13
|
+
this.counter = -1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
addPlug(plug) {
|
|
17
|
+
this.plugs.push(plug);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exec(completionCallback) {
|
|
21
|
+
this.completionCallback = completionCallback;
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
this.resolve = resolve;
|
|
24
|
+
this.reject = reject;
|
|
25
|
+
this.nextplug();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
exec(completionCallback) {
|
|
31
|
+
this.completionPromise = new Promise((resolve, reject) => {
|
|
32
|
+
console.log("The context", context)
|
|
33
|
+
const plug = this.nextplug();
|
|
34
|
+
if (!plug) {
|
|
35
|
+
console.log("NO PLUGS!");
|
|
36
|
+
if (completionCallback) {
|
|
37
|
+
console.log("completionCallback found.");
|
|
38
|
+
completionCallback();
|
|
39
|
+
}
|
|
40
|
+
console.log("Resolving...", this.message);
|
|
41
|
+
return resolve();
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
plug.exec(this, () => {
|
|
45
|
+
if (completionCallback) {
|
|
46
|
+
console.log("completionCallback found.");
|
|
47
|
+
completionCallback();
|
|
48
|
+
}
|
|
49
|
+
console.log("Resolving...", this.message);
|
|
50
|
+
return resolve();
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return this.completionPromise;
|
|
55
|
+
}
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/*execOn(message, context, completionCallback) {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
this.message = message;
|
|
61
|
+
console.log("The context", context)
|
|
62
|
+
this.process(this.nextplug(), context, (message) => {
|
|
63
|
+
console.log("All plugs processed.", message)
|
|
64
|
+
if (completionCallback) {
|
|
65
|
+
console.log("completionCallback found.")
|
|
66
|
+
completionCallback(message);
|
|
67
|
+
}
|
|
68
|
+
console.log("Resolving...", message)
|
|
69
|
+
return resolve(message);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}*/
|
|
73
|
+
|
|
74
|
+
/*process(plug, context, completionCallback) {
|
|
75
|
+
if (plug) {
|
|
76
|
+
plug.execOn(this.message, context, () => {
|
|
77
|
+
this.process(this.nextplug(), context, completionCallback);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
completionCallback(this.message);
|
|
82
|
+
}
|
|
83
|
+
}*/
|
|
84
|
+
|
|
85
|
+
nextplug() {
|
|
86
|
+
this.counter += 1;
|
|
87
|
+
console.log(`processing plug[${this.counter}]`);
|
|
88
|
+
if (this.counter < this.plugs.length) {
|
|
89
|
+
console.log("Still plugs...")
|
|
90
|
+
let nextp = this.plugs[this.counter];
|
|
91
|
+
console.log("nextp is:", nextp)
|
|
92
|
+
nextp.exec(this);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
console.log("no more plugs");
|
|
96
|
+
this.resolve(this.message);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/*
|
|
100
|
+
nextplug() {
|
|
101
|
+
this.counter += 1;
|
|
102
|
+
console.log(`processing plug[${this.counter}]`);
|
|
103
|
+
if (this.counter < this.plugs.length) {
|
|
104
|
+
let nextp = this.plugs[this.counter];
|
|
105
|
+
return nextp;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
console.log("no more plugs");
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = { MessagePipeline };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const { TiledeskChatbotUtil } = require('@tiledesk/tiledesk-chatbot-util');
|
|
2
|
+
|
|
3
|
+
class SplitsChatbotPlug {
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @example
|
|
8
|
+
* const { SplitsChatbotPlug } = require('./SplitsChatbotPlug');
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
constructor() {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exec(pipeline) {
|
|
16
|
+
let message = pipeline.message;
|
|
17
|
+
if (message.attributes && message.attributes.splits && message.attributes.splits == false) {
|
|
18
|
+
completionCallback(message);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
console.log("Splitting...")
|
|
22
|
+
// if splits found just a attributs.commands payload is attached
|
|
23
|
+
// to the original json message with split commands
|
|
24
|
+
let commands = TiledeskChatbotUtil.splitPars(message.text);
|
|
25
|
+
console.log("commands", commands)
|
|
26
|
+
if (commands && commands.length > 1) {
|
|
27
|
+
if (!message.attributes) {
|
|
28
|
+
message.attributes = {}
|
|
29
|
+
}
|
|
30
|
+
message.attributes.commands = commands;
|
|
31
|
+
}
|
|
32
|
+
console.log("Message out of Splits plugin:", JSON.stringify(message));
|
|
33
|
+
pipeline.nextplug();
|
|
34
|
+
//next(pipeline, completionCallback);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
next(pipeline, completionCallback) {
|
|
38
|
+
const plug = pipeline.nextplug();
|
|
39
|
+
if (!plug) {
|
|
40
|
+
completionCallback();
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
plug.exec(pipeline);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = { SplitsChatbotPlug };
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
let axios = require('axios');
|
|
2
|
+
|
|
3
|
+
class WebhookChatbotPlug {
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @example
|
|
7
|
+
* const { DirectivesChatbotPlug } = require('./DirectivesChatbotPlug');
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
constructor(supportRequest, webhookurl, token) {
|
|
12
|
+
this.supportRequest = supportRequest;
|
|
13
|
+
this.webhookurl = webhookurl;
|
|
14
|
+
this.token = token;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exec(pipeline) {
|
|
18
|
+
let message = pipeline.message;
|
|
19
|
+
let context = pipeline.context;
|
|
20
|
+
console.log("EXECUTIN WEBHOOK", message.attributes)
|
|
21
|
+
console.log("EXECUTIN WEBHOOK.webhook", message.attributes.webhook)
|
|
22
|
+
console.log("EXECUTIN WEBHOOK", message.attributes)
|
|
23
|
+
if (message.attributes && message.attributes.webhook && message.attributes.webhook === true) {
|
|
24
|
+
console.log("EXECUTING WEBHOOK!", this.webhookurl);
|
|
25
|
+
this.execWebhook(message, context, this.webhookurl, (err, message_from_webhook) => {
|
|
26
|
+
console.log("Err", err)
|
|
27
|
+
console.log("message", message_from_webhook)
|
|
28
|
+
if (err) {
|
|
29
|
+
console.error("Error calling webhook", this.webhookurl)
|
|
30
|
+
pipeline.nextplug();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.log("Webhook successfully end:", message_from_webhook);
|
|
34
|
+
pipeline.message = message_from_webhook;
|
|
35
|
+
pipeline.nextplug();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log("NO WEBHOOK!");
|
|
41
|
+
pipeline.nextplug();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
console.log("Start processing webhook...");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
execWebhook(reply_message, context, webhookurl, callback) {
|
|
48
|
+
console.log("WEBHOOK. on context", context)
|
|
49
|
+
console.log("WEBHOOK. on message", reply_message)
|
|
50
|
+
const HTTPREQUEST = {
|
|
51
|
+
url: webhookurl,
|
|
52
|
+
headers: {
|
|
53
|
+
'Content-Type' : 'application/json',
|
|
54
|
+
'User-Agent': 'tiledesk-bot',
|
|
55
|
+
'Origin': "pre"
|
|
56
|
+
},
|
|
57
|
+
json: context,
|
|
58
|
+
method: 'POST'
|
|
59
|
+
};
|
|
60
|
+
WebhookChatbotPlug.myrequest(
|
|
61
|
+
HTTPREQUEST,
|
|
62
|
+
function(err, res) {
|
|
63
|
+
if (err || (res && res.status >= 400) || (res && !res.data)) {
|
|
64
|
+
console.error("An error occurred calling intent's webhook url:", webhookurl);
|
|
65
|
+
if (callback) {
|
|
66
|
+
callback(reply_message);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.log("Hello", res.data)
|
|
71
|
+
if (callback) {
|
|
72
|
+
callback(null, res.data);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}, this.log
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
return request({
|
|
80
|
+
uri : webhookurl,
|
|
81
|
+
headers: {
|
|
82
|
+
'Content-Type' : 'application/json',
|
|
83
|
+
'User-Agent': 'tiledesk-bot',
|
|
84
|
+
'Origin': webhook_origin
|
|
85
|
+
//'x-hook-secret': s.secret
|
|
86
|
+
},
|
|
87
|
+
method: 'POST',
|
|
88
|
+
json: true,
|
|
89
|
+
body: {payload:{text: text, bot: bot, message: message, intent: faq}, token: token},
|
|
90
|
+
// }).then(response => {
|
|
91
|
+
}, function(err, response, json){
|
|
92
|
+
if (err) {
|
|
93
|
+
winston.error("Error from webhook reply of getParsedMessage. Return standard reply", err);
|
|
94
|
+
|
|
95
|
+
return resolve(messageReply);
|
|
96
|
+
|
|
97
|
+
// return error
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
if (response.statusCode >= 400) {
|
|
101
|
+
winston.verbose("The ChatBot webhook return error http status code. Return standard reply", response);
|
|
102
|
+
return resolve(messageReply);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!json) { //the webhook return empty body
|
|
106
|
+
winston.verbose("The ChatBot webhook return no json. Return standard reply", response);
|
|
107
|
+
return resolve(messageReply);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
winston.debug("webhookurl repl_message ", response);
|
|
111
|
+
|
|
112
|
+
var text = undefined;
|
|
113
|
+
if(json && json.text===undefined) {
|
|
114
|
+
winston.verbose("webhookurl json is defined but text not. return standard reply",{json:json, response:response});
|
|
115
|
+
// text = 'Field text is not defined in the webhook respose of the faq with id: '+ faq._id+ ". Error: " + JSON.stringify(response);
|
|
116
|
+
return resolve(messageReply);
|
|
117
|
+
}else {
|
|
118
|
+
text = json.text;
|
|
119
|
+
}
|
|
120
|
+
winston.debug("webhookurl text: "+ text);
|
|
121
|
+
|
|
122
|
+
// // let cloned_message = Object.assign({}, messageReply);
|
|
123
|
+
// let cloned_message = message;
|
|
124
|
+
// winston.debug("cloned_message : ",cloned_message);
|
|
125
|
+
|
|
126
|
+
// if (json.attributes) {
|
|
127
|
+
// if (!cloned_message.attributes) {
|
|
128
|
+
// cloned_message.attributes = {}
|
|
129
|
+
// }
|
|
130
|
+
// winston.debug("ChatBot webhook json.attributes: ",json.attributes);
|
|
131
|
+
// for(const [key, value] of Object.entries(json.attributes)) {
|
|
132
|
+
// cloned_message.attributes[key] = value
|
|
133
|
+
// }
|
|
134
|
+
// }
|
|
135
|
+
|
|
136
|
+
// winston.debug("cloned_message after attributes: ",cloned_message);
|
|
137
|
+
|
|
138
|
+
that.parseMicrolanguage(text, message, bot, faq, true, json).then(function(bot_answer) {
|
|
139
|
+
return resolve(bot_answer);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
*/
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ************************************************
|
|
146
|
+
// ****************** HTTP REQUEST ****************
|
|
147
|
+
// ************************************************
|
|
148
|
+
|
|
149
|
+
static myrequest(options, callback, log) {
|
|
150
|
+
if (log) {
|
|
151
|
+
console.log("API URL:", options.url);
|
|
152
|
+
console.log("** Options:", options);
|
|
153
|
+
}
|
|
154
|
+
axios(
|
|
155
|
+
{
|
|
156
|
+
url: options.url,
|
|
157
|
+
method: options.method,
|
|
158
|
+
data: options.json,
|
|
159
|
+
headers: options.headers
|
|
160
|
+
})
|
|
161
|
+
.then(function (res) {
|
|
162
|
+
if (log) {
|
|
163
|
+
console.log("Response for url:", options.url);
|
|
164
|
+
console.log("Response headers:\n", res.headers);
|
|
165
|
+
console.log("******** Response for url:", res);
|
|
166
|
+
console.log("Response body:\n", res.data);
|
|
167
|
+
}
|
|
168
|
+
if (callback) {
|
|
169
|
+
callback(null, res);
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
.catch(function (error) {
|
|
173
|
+
console.error("An error occurred:", error);
|
|
174
|
+
if (callback) {
|
|
175
|
+
callback(error, null, null);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
module.exports = { WebhookChatbotPlug };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tiledesk/tiledesk-chatbot-plugs",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Tiledesk Chatbot Plugs",
|
|
5
|
+
"engines": {
|
|
6
|
+
"node": ">=12.x"
|
|
7
|
+
},
|
|
8
|
+
"main": "index.js",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/Tiledesk/tiledesk-chatbot.git"
|
|
15
|
+
},
|
|
16
|
+
"author": "Andrea Sponziello",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/Tiledesk/tiledesk-chatbot/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/Tiledesk/tiledesk-chatbot#readme",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@tiledesk/tiledesk-chatbot-util": "^0.8.36",
|
|
24
|
+
"@tiledesk/tiledesk-client": "^0.8.28",
|
|
25
|
+
"axios": "^0.27.2"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#npm version patch
|
|
2
|
+
version=`node -e 'console.log(require("./package.json").version)'`
|
|
3
|
+
echo "version $version"
|
|
4
|
+
|
|
5
|
+
if [ "$version" != "" ]; then
|
|
6
|
+
git tag -a "$version" -m "`git log -1 --format=%s`"
|
|
7
|
+
echo "Created a new tag, $version"
|
|
8
|
+
git push --tags
|
|
9
|
+
npm publish --access public
|
|
10
|
+
fi
|