@tiledesk/tiledesk-tybot-connector 2.0.38 → 2.0.40
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/engine/TiledeskChatbot.js +60 -3
- package/engine/mock/MockBotsDataSource.js +1 -1
- package/index.js +154 -3
- package/logs/app.log +110 -0
- package/package.json +1 -1
- package/services/TilebotService.js +36 -0
- package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +100 -519
- package/tiledeskChatbotPlugs/directives/DirAddKbContent.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirAddTags.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirAiCondition.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirAiPrompt.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirAskGPTV2.js +2 -2
- package/tiledeskChatbotPlugs/directives/DirAssistant.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirBrevo.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirCaptureUserReply.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirClearTranscript.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirClose.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirCode.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirCondition.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirContactUpdate.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirCustomerio.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirDeleteVariable.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirDepartment.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirFlowLog.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirGptTask.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirHubspot.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirIfOnlineAgentsV2.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirIfOpenHours.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirIntent.js +4 -0
- package/tiledeskChatbotPlugs/directives/DirJSONCondition.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirMake.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirMoveToAgent.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirMoveToUnassigned.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirQapla.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirRandomReply.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirReplaceBot.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirReplaceBotV2.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirReplaceBotV3.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirReply.js +10 -2
- package/tiledeskChatbotPlugs/directives/DirReplyV2.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirSendEmail.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirSendWhatsapp.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirSetAttributeV2.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirWait.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirWebRequestV2.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirWebResponse.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirWhatsappByAttribute.js +1 -1
- package/utils/TiledeskChatbotUtil.js +131 -141
|
@@ -18,9 +18,9 @@ class TiledeskChatbot {
|
|
|
18
18
|
if (!config.botsDataSource) {
|
|
19
19
|
throw new Error("config.botsDataSource is mandatory");
|
|
20
20
|
}
|
|
21
|
-
if (!config.intentsFinder) {
|
|
22
|
-
|
|
23
|
-
}
|
|
21
|
+
// if (!config.intentsFinder) {
|
|
22
|
+
// throw new Error("config.intentsFinder is mandatory");
|
|
23
|
+
// }
|
|
24
24
|
if (!config.botId) {
|
|
25
25
|
throw new Error("config.botId is mandatory");
|
|
26
26
|
}
|
|
@@ -253,6 +253,63 @@ class TiledeskChatbot {
|
|
|
253
253
|
}
|
|
254
254
|
});
|
|
255
255
|
}
|
|
256
|
+
|
|
257
|
+
async findBlock(message, callback) {
|
|
258
|
+
return new Promise( async (resolve, reject) => {
|
|
259
|
+
let lead = null;
|
|
260
|
+
if (message.request) {
|
|
261
|
+
this.request = message.request;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
let explicit_intent_name = null;
|
|
265
|
+
// Explicit intent invocation
|
|
266
|
+
if (message.text && message.text.startsWith("/")) {
|
|
267
|
+
winston.verbose("(TiledeskChatbot) Intent was explicitly invoked: " + message.text);
|
|
268
|
+
let intent_name = message.text.substring(message.text.indexOf("/") + 1);
|
|
269
|
+
winston.verbose("(TiledeskChatbot) Invoked Intent: " + intent_name)
|
|
270
|
+
explicit_intent_name = intent_name;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Intent invocation with action
|
|
274
|
+
if (message.attributes && message.attributes.action) {
|
|
275
|
+
winston.debug("(TiledeskChatbot) Message has action: ", message.attributes.action)
|
|
276
|
+
explicit_intent_name = message.attributes.action;
|
|
277
|
+
winston.verbose("(TiledeskChatbot) Intent was explicitly invoked with an action:", explicit_intent_name)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (explicit_intent_name) {
|
|
281
|
+
winston.verbose("(TiledeskChatbot) Processing explicit intent:", explicit_intent_name)
|
|
282
|
+
// look for parameters
|
|
283
|
+
const intent = TiledeskChatbotUtil.parseIntent(explicit_intent_name);
|
|
284
|
+
winston.debug("(TiledeskChatbot) parsed intent:", intent);
|
|
285
|
+
let reply;
|
|
286
|
+
if (!intent || (intent && !intent.name)) {
|
|
287
|
+
winston.verbose("(TiledeskChatbot) Invalid intent:", explicit_intent_name)
|
|
288
|
+
reply = { "text": "Invalid intent: *" + explicit_intent_name + "*" }
|
|
289
|
+
resolve();
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
winston.verbose("(TiledeskChatbot) Processing intent:", explicit_intent_name)
|
|
293
|
+
let faq = await this.botsDataSource.getByIntentDisplayNameCache(this.botId, intent.name, this.tdcache);
|
|
294
|
+
// console.log("faq: ", JSON.stringify(faq, null, 2))
|
|
295
|
+
|
|
296
|
+
if (faq) {
|
|
297
|
+
if (faq.actions) {
|
|
298
|
+
// Qui viene aggiornata faq perchè l'oggetto in js viene passato per riferimento. Viene modificato l'oggetto originale anche senza un return.
|
|
299
|
+
TiledeskChatbotUtil.addConnectAction(faq);
|
|
300
|
+
}
|
|
301
|
+
resolve(faq)
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
winston.verbose("(TiledeskChatbot) Intent not found: " + explicit_intent_name);
|
|
306
|
+
reply = { "text": "Intent not found: " + explicit_intent_name }
|
|
307
|
+
resolve()
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|
|
256
313
|
|
|
257
314
|
async execIntent(faq, message, lead) {//, bot) {
|
|
258
315
|
let answerObj = faq; // faqs[0];
|
|
@@ -38,7 +38,7 @@ class MockBotsDataSource {
|
|
|
38
38
|
* @returns an Array of matches
|
|
39
39
|
*/
|
|
40
40
|
async getByExactMatch(botId, text) {
|
|
41
|
-
const intent_display_name = this.data.bots[botId].questions_intent[text];
|
|
41
|
+
const intent_display_name = this.data.bots[botId].questions_intent?.[text];
|
|
42
42
|
if (intent_display_name) {
|
|
43
43
|
return [this.data.bots[botId].intents[intent_display_name]];
|
|
44
44
|
}
|
package/index.js
CHANGED
|
@@ -44,6 +44,7 @@ let staticBots;
|
|
|
44
44
|
router.post('/ext/:botid', async (req, res) => {
|
|
45
45
|
const botId = req.params.botid;
|
|
46
46
|
winston.verbose("(tybotRoute) POST /ext/:botid called: " + botId)
|
|
47
|
+
|
|
47
48
|
if(!botId || botId === "null" || botId === "undefined"){
|
|
48
49
|
return res.status(400).send({"success": false, error: "Required parameters botid not found. Value is 'null' or 'undefined'"})
|
|
49
50
|
}
|
|
@@ -133,9 +134,14 @@ router.post('/ext/:botid', async (req, res) => {
|
|
|
133
134
|
});
|
|
134
135
|
winston.verbose("(tybotRoute) Message text: " + message.text)
|
|
135
136
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
try {
|
|
138
|
+
await TiledeskChatbotUtil.updateRequestAttributes(chatbot, token, message, projectId, requestId);
|
|
139
|
+
if (requestId.startsWith("support-group-")) {
|
|
140
|
+
await TiledeskChatbotUtil.updateConversationTranscript(chatbot, message);
|
|
141
|
+
}
|
|
142
|
+
} catch (e) {
|
|
143
|
+
winston.error("Error on /ext updating request attributes or transcript: ", e)
|
|
144
|
+
return;
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
let reply = null;
|
|
@@ -199,6 +205,151 @@ router.post('/ext/:botid', async (req, res) => {
|
|
|
199
205
|
|
|
200
206
|
});
|
|
201
207
|
|
|
208
|
+
router.post('/exec/:botid', async (req, res) => {
|
|
209
|
+
|
|
210
|
+
const botId = req.params.botid;
|
|
211
|
+
winston.verbose("(tybotRoute) POST /exec/:botid called: " + botId);
|
|
212
|
+
if(!botId || botId === "null" || botId === "undefined"){
|
|
213
|
+
return res.status(400).send({"success": false, error: "Required parameters botid not found. Value is 'null' or 'undefined'"})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (req && req.body && req.body.payload && req.body.payload.request && req.body.payload.request.snapshot) {
|
|
217
|
+
delete req.body.payload.request.snapshot;
|
|
218
|
+
}
|
|
219
|
+
winston.verbose("(tybotRoute) Request Body: ", req.body);
|
|
220
|
+
|
|
221
|
+
const message = req.body.payload;
|
|
222
|
+
const messageId = message._id;
|
|
223
|
+
const token = req.body.token;
|
|
224
|
+
const requestId = message.request.request_id;
|
|
225
|
+
const projectId = message.id_project;
|
|
226
|
+
winston.verbose("(tybotRoute) message.id_project: " + message.id_project)
|
|
227
|
+
|
|
228
|
+
// adding info for internal context workflow
|
|
229
|
+
message.request.bot_id = botId;
|
|
230
|
+
if (message.request.id_project === null || message.request.id_project === undefined) {
|
|
231
|
+
message.request.id_project = projectId;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
//skip internal note messages
|
|
235
|
+
if(message && message.attributes && message.attributes.subtype === 'private') {
|
|
236
|
+
winston.verbose("(tybotRoute) Skipping internal note message: " + message.text);
|
|
237
|
+
return res.status(200).send({"success":true});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// validate reuqestId
|
|
241
|
+
let isValid = TiledeskChatbotUtil.validateRequestId(requestId, projectId);
|
|
242
|
+
if (isValid) {
|
|
243
|
+
res.status(200).send({"success":true});
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
res.status(400).send({"success": false, error: "Request id is invalid:" + requestId + " for projectId:" + projectId + "chatbotId:" + botId});
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const request_botId_key = "tilebot:botId_requests:" + requestId;
|
|
251
|
+
await tdcache.set(
|
|
252
|
+
request_botId_key,
|
|
253
|
+
botId,
|
|
254
|
+
{EX: 604800} // 7 days
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
let botsDS;
|
|
258
|
+
if (!staticBots) {
|
|
259
|
+
botsDS = new MongodbBotsDataSource({projectId: projectId, botId: botId});
|
|
260
|
+
winston.verbose("(tybotRoute) botsDS created with Mongo");
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
botsDS = new MockBotsDataSource(staticBots);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// get the bot metadata
|
|
267
|
+
let bot = await botsDS.getBotByIdCache(botId, tdcache).catch((err)=> {
|
|
268
|
+
Promise.reject(err);
|
|
269
|
+
return;
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
let intentsMachine;
|
|
273
|
+
let backupMachine;
|
|
274
|
+
|
|
275
|
+
const chatbot = new TiledeskChatbot({
|
|
276
|
+
botsDataSource: botsDS,
|
|
277
|
+
intentsFinder: intentsMachine,
|
|
278
|
+
backupIntentsFinder: backupMachine,
|
|
279
|
+
botId: botId,
|
|
280
|
+
bot: bot,
|
|
281
|
+
token: token,
|
|
282
|
+
APIURL: API_ENDPOINT,
|
|
283
|
+
APIKEY: "___",
|
|
284
|
+
tdcache: tdcache,
|
|
285
|
+
requestId: requestId,
|
|
286
|
+
projectId: projectId,
|
|
287
|
+
MAX_STEPS: MAX_STEPS,
|
|
288
|
+
MAX_EXECUTION_TIME: MAX_EXECUTION_TIME
|
|
289
|
+
});
|
|
290
|
+
winston.verbose("(tybotRoute) Message text: " + message.text);
|
|
291
|
+
|
|
292
|
+
let reply = null;
|
|
293
|
+
try {
|
|
294
|
+
reply = await chatbot.findBlock(message);
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
winston.error("(tybotRoute) An error occurred replying to message: ", err);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (!reply) {
|
|
301
|
+
winston.verbose("(tybotRoute) No reply. Stop flow.")
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (reply.actions && reply.actions.length > 0) { // structured actions (coming from chatbot designer)
|
|
306
|
+
try {
|
|
307
|
+
winston.debug("(tybotRoute) Reply actions: ", reply.actions)
|
|
308
|
+
let directives = TiledeskChatbotUtil.actionsToDirectives(reply.actions);
|
|
309
|
+
winston.debug("(tybotRoute) the directives:", directives)
|
|
310
|
+
let directivesPlug = new DirectivesChatbotPlug(
|
|
311
|
+
{
|
|
312
|
+
message: message,
|
|
313
|
+
reply: reply,
|
|
314
|
+
directives: directives,
|
|
315
|
+
chatbot: chatbot,
|
|
316
|
+
supportRequest: message.request,
|
|
317
|
+
API_ENDPOINT: API_ENDPOINT,
|
|
318
|
+
TILEBOT_ENDPOINT:TILEBOT_ENDPOINT,
|
|
319
|
+
token: token,
|
|
320
|
+
// HELP_CENTER_API_ENDPOINT: process.env.HELP_CENTER_API_ENDPOINT,
|
|
321
|
+
cache: tdcache
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
directivesPlug.processDirectives( () => {
|
|
325
|
+
winston.verbose("(tybotRoute) Actions - Directives executed.");
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
winston.error("(tybotRoute) Error while processing actions:", error);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else { // text answer (parse text directives to get actions)
|
|
333
|
+
winston.verbose("(tybotRoute) No actions. Reply text: ", reply.text)
|
|
334
|
+
reply.triggeredByMessageId = messageId;
|
|
335
|
+
if (!reply.attributes) {
|
|
336
|
+
reply.attributes = {}
|
|
337
|
+
}
|
|
338
|
+
reply.attributes.directives = true;
|
|
339
|
+
reply.attributes.splits = true;
|
|
340
|
+
reply.attributes.markbot = true;
|
|
341
|
+
reply.attributes.fillParams = true;
|
|
342
|
+
|
|
343
|
+
const apiext = new ExtApi({
|
|
344
|
+
TILEBOT_ENDPOINT: TILEBOT_ENDPOINT
|
|
345
|
+
});
|
|
346
|
+
apiext.sendSupportMessageExt(reply, projectId, requestId, token, () => {
|
|
347
|
+
winston.verbose("(tybotRoute) sendSupportMessageExt reply sent: ", reply)
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
})
|
|
352
|
+
|
|
202
353
|
router.post('/ext/:projectId/requests/:requestId/messages', async (req, res) => {
|
|
203
354
|
res.json({success:true});
|
|
204
355
|
const projectId = req.params.projectId;
|