poserver
Version:
Server for JD Bot
247 lines (209 loc) • 8.97 kB
JavaScript
/**
* Created by tomdaley on 11/18/16.
*/
var builder = require('botbuilder');
var params = require("../../../poserver-configuration.json");
var prompts = require('../const/prompts');
var _created = false;
module.exports =
{
create: function (bot)
{
if (_created) return;
_created = true;
//Create the BUILTIN library if we don't already have it.
if (!bot.lib.libraries.hasOwnProperty("BUILTIN"))
bot.library(new builder.Library('BUILTIN'));
var navigationRecognizer = new builder.LuisRecognizer(params.LUIS_SERVICE_NAVIGATION);
var confirmDialog = new builder.IntentDialog({recognizers: [navigationRecognizer]});
confirmDialog.matches(/^(1|y|yes|yep|sure|ok|si|true)/i, function (session)
{
session.endDialogWithResult({response: true});
});
confirmDialog.matches(/^(2|n|no|nope|not|false)/i, function (session)
{
session.endDialogWithResult({response: false});
});
var backWaterfall = [
function (session)
{
session.endDialogWithResult({navigation: "back"});
}
];
//RegEx processed before LUIS recognizer is called. Some really obvious/common regex patterns will reduce the number
//of LUIS API calls. Will make the app run faster and cheaper.
confirmDialog.matches(/^(back|go back|prev|up)/i, backWaterfall);
confirmDialog.matches('navigation.intent.goback', backWaterfall);
var helpWaterfall = [
function (session, args, next)
{
if (session.dialogData.config.hasOwnProperty('helpDialog'))
{
session.beginDialog(session.dialogData.config.helpDialog);
}
else if (session.dialogData.config.hasOwnProperty('helpMessage'))
{
session.send(session.dialogData.config.helpMessage);
next();
}
else
{
session.send(prompts.sayICantHelpYou);
next();
}
},
function (session)
{
var showHelp = (session.dialogData.config.helpDialog || session.dialogData.config.helpMessage);
confirm(session, session.dialogData.config.prompt, showHelp);
}
];
confirmDialog.matches(/^(help|\?)/i, helpWaterfall);
confirmDialog.matches('navigation.intent.help', helpWaterfall);
confirmDialog.matches('navigation.intent.explain',
[
function (session, args, next)
{
if (session.dialogData.config.hasOwnProperty('explainDialog'))
{
session.beginDialog(session.dialogData.config.explainDialog);
}
else if (session.dialogData.config.hasOwnProperty('explainMessage'))
{
session.send(session.dialogData.config.explainMessage);
next();
}
else
{
session.send(prompts.sayIDontKnowWhy);
next();
}
},
function (session)
{
var showHelp = (session.dialogData.config.helpDialog || session.dialogData.config.helpMessage);
confirm(session, session.dialogData.config.prompt, showHelp);
}
]);
var restartWaterfall = [
function (session)
{
session.endDialogWithResult({navigation: "restart"});
}
];
confirmDialog.matches(/^(restart|start over)/i, restartWaterfall);
confirmDialog.matches('navigation.intent.restart', restartWaterfall);
var quitWaterfall = [
function (session)
{
session.endDialogWithResult({navigation: "quit"});
}
];
confirmDialog.matches(/^(quit|abort)/i, quitWaterfall);
confirmDialog.matches('navigation.intent.quit', quitWaterfall);
confirmDialog.onDefault(function (session)
{
var showHelp = (session.dialogData.config.helpDialog || session.dialogData.config.helpMessage);
confirm(session, session.dialogData.config.prompt, showHelp);
});
confirmDialog.onBegin(function (session, config)
{
session.dialogData.config = config || {};
var showHelp = (session.dialogData.config.helpDialog || session.dialogData.config.helpMessage);
confirm(session, config.prompt, showHelp);
});
/** @property {object} bot.lib.libraries.BUILTIN */
bot.lib.libraries.BUILTIN.dialog('/confirm', confirmDialog);
},
/**
*
* @param session
* @param {object} config - Config object or prompt string if no further configuration needed.
*
* @namespace
* @property {string} config.prompt - Text to prompt the user with
* @property {string} config.explainDialog - [OPTIONAL] Name of dialog that explains why we're asking.
* @property {string} config.explainMessage - [OPTIONAL] String that explains why we're asking.
* @property {string} config.helpDialog - [OPTIONAL] Name of dialog that provides help for this prompt.
* @property {string} config.helpMessage - [OPTIONAL] String that provides help for this prompt.
*/
confirm: function (session, config)
{
if (typeof config == "string")
{
config = {prompt: config};
}
config = config || {};
if (!config.hasOwnProperty("prompt")) throw new Error("ConfirmDialog.confirm(): config element must have 'prompt' property.");
session.beginDialog('BUILTIN:/confirm', config);
}
};
/**
* My version of the confirm (Yes|No) prompt. This is used in combination with the *:/confirm dialog. It presents
* a standard-looking Yes|No prompt, but it also uses a LuisRecognizer to to handle out of band responses where
* the user wants to go back a question, abort this train of talk, end the entire conversation, or understand
* why we are asking this question.
*
* @param session
* @param prompt - Can be a string or an array of strings.
* @param showHelp - [OPTIONAL] True to show a "Help" button, which will postback a "?" mark.
*/
const fs = require('fs');
const yesIconPath = "images/yes-icon.png";
const noIconPath = "images/no-icon.png";
const helpIconPath = "images/help-icon.png";
function confirm(session, prompt, showHelp)
{
showHelp = showHelp || false;
//Create a YES button
var yesAction = builder.CardAction.postBack(session, "Y", prompts.yes);
if (!fs.existsSync(yesIconPath))
{
console.info("ConfirmDialog.configm(): %s not found.", yesIconPath);
}
else
{
var yesPath = fs.realpathSync(yesIconPath).replace(/\\/g, "/");
if (yesPath.slice(0, 0) != "/") yesPath = "/" + yesPath; //when running under Windows
yesAction.image(encodeURI("file://" + yesPath));
console.log(encodeURI("file://" + yesPath));
}
//Create a NO button
var noAction = builder.CardAction.postBack(session, "N", prompts.no);
if (!fs.existsSync(noIconPath))
{
console.info("ConfirmDialog.configm(): %s not found.", noIconPath);
}
else
{
var noPath = fs.realpathSync(noIconPath).replace(/\\/g, "/");
if (noPath.slice(0, 0) != "/") noPath = "/" + noPath; //when running under Windows
noAction.image(encodeURI("file:///" + noPath));
console.log(encodeURI("file:///" + noPath));
}
//We also ask at least YES or NO, so add them to the choices array
var xchoices = [yesAction, noAction];
//If the calling dialog can provide help, then add a HELP button to the mix.
if (showHelp)
{
var helpAction = builder.CardAction.postBack(session, "?", prompts.help);
if (!fs.existsSync(helpIconPath))
{
console.info("ConfirmDialog.configm(): %s not found.", helpIconPath);
}
else
{
var helpPath = fs.realpathSync(helpIconPath).replace(/\\/g, "/");
if (helpPath.slice(0, 0) != "/") helpPath = "/" + helpPath; //when running under Windows
helpAction.image(encodeURI("file:///" + helpPath));
console.log(encodeURI("file:///" + helpPath));
}
xchoices.push(helpAction);
}
var myText = (Array.isArray(prompt)) ? prompt[Math.floor(Math.random() * prompt.length)] : prompt;
var card = new builder.HeroCard(session)
.text(myText)
.buttons(xchoices);
var msg = new builder.Message(session).addAttachment(card);
session.send(msg);
}