poserver
Version:
Server for JD Bot
337 lines (281 loc) • 10.9 kB
JavaScript
/**
* Created by tomdaley on 9/4/16.
*/
;
var myPackage = require('./package.json');
var Util = require('./JdBotUtil');
var mongoUtil = require('./classes/mongoUtils');
/*********************************************
* Classes use in session.userData
*********************************************/
var ParsedAddress = require('./classes/clsParsedAddress');
var ParsedName = require('./classes/clsParsedName');
var Person = require('./classes/clsPerson');
var Types = require('./classes/types');
Types.registerType("ParsedAddress", ParsedAddress);
Types.registerType("ParsedName", ParsedName);
Types.registerType("Person", Person);
var restify = require('restify');
var builder = require('botbuilder');
/*********************************************
* Runtime Environment
*********************************************/
var params = require("../../poserver-configuration.json");
/*********************************************
* Prompts - Externalized for localization
*********************************************/
var prompts = require('./const/prompts');
/*********************************************
* Connect to Mongo DB for user Auth and
* data persistence.
*********************************************/
mongoUtil.connectDb(function (err)
{
console.log('Connected to MongoDb at %s', params.MONGODBURL);
Util.loadViolenceDatabase();
});
/*********************************************
* Bot Setup
*********************************************/
// Setup Restify Server
var server = restify.createServer();
server.listen(params.PORT, function ()
{
console.log("%s - %s (v %s) by %s", myPackage.name, myPackage.description, myPackage.version, myPackage.author.name);
console.log('%s listening to %s', server.name, server.url);
});
//Create chat bot
var connector = new builder.ChatConnector(
{
appId : params.MICROSOFT_APP_ID,
appPassword: params.MICROSOFT_APP_PASSWORD
}
);
var bot = new builder.UniversalBot(connector);
/*********************************************
* Imported Dialogs
*********************************************/
bot.library(require('./dialogs/AddressDialog'));
bot.library(require('./dialogs/CauseNumberDialog'));
bot.library(require('./dialogs/CustomerSurveyLibrary'));
bot.library(require('./dialogs/CountyDialog'));
bot.library(require('./dialogs/OriginalAnswerDialogs'));
bot.library(require('./dialogs/PaymentDialogs'));
bot.library(require('./dialogs/QualifyJurisdictionDialog'));
bot.library(require('./dialogs/UserProfileDialogs'));
var ConfirmDialog = require("./dialogs/ConfirmDialog");
ConfirmDialog.create(bot);
var ChoiceDialog = require("./dialogs/ChoiceDialog");
ChoiceDialog.create(bot);
var FVProtectiveOrder = require('./dialogs/FamilyViolenceProtectiveOrder');
server.post('/api/messages', connector.listen());
/*********************************************
* Bot's Dialogs
*********************************************/
Util.setBot(bot);
FVProtectiveOrder.createDialogs(bot, builder);
//See if the user's profile needs to be updated or we need to do anything else by reason of a software update since the
//last time the user was here.
bot.use(builder.Middleware.firstRun({
version : 4.5, dialogId: 'userProfile:/firstRun',
upgradeDialogId: 'userProfile:/upgrade', upgradeDialogArgs: {toVersion: "4.5"}
}));
/*
* On each incoming message from the user, see what kind of a delay there was since the last message.
* On an insignificant delay, just continue.
* On a minor but noticeable delay, welcome the user back, reload his or her profile, and continue.
* On a major delay, start the conversation over.
*
* In the future we could log the delay relating to each question and see if user's tend to get stuck in the same
* place or places.
*/
var checker = function (options)
{
var mw =
{
botbuilder: function (session, next)
{
if (!session.userData.hasOwnProperty("lastBotbuilderTime"))
session.userData.lastBotbuilderTime = (new Date()).getTime();
var delay = (new Date()).getTime() - session.userData.lastBotbuilderTime;
session.userData.lastBotbuilderTime = (new Date()).getTime();
//////// Here to reinstantiate userData as a class with methods, not just data
if (session.userData.hasOwnProperty("userProfile"))
session.userData.userProfile = Types.revive(session.userData.userProfile);
if (session.userData.hasOwnProperty("case"))
session.userData.case = Types.revive(session.userData.case);
//////// END REINSTANTIATE
//Minor Delay
/** @property {number} mwDelayMilliseconds - Less than this # ms between messages = active session */
if (delay > params.mwDelayMilliseconds && delay < params.mwDelayRestartMilliseconds)
{
/**
* @param session - Our ever-present session object
* @param {boolean} isLoaded - Indicates whether the profile was successfully reloaded
*/
Util.getUserProfile(session)
.then(function (isLoaded)
{
var salutation = (session.userData.hasOwnProperty("userProfile") ? session.userData.userProfile.name.salutation :
session.message.user.name);
var prompt = session.gettext(Util.getRandomElement(prompts.sayWelcomeAfterDelay), {uname: salutation});
session.send(prompt);
next();
})
.catch(function (reason)
{
console.log("Error loading userProfile");
console.log(reason);
});
}
//Major Delay
/**
* @property {number} mwDelayRestartMilliseconds - After the user has been inactive this # ms, we restart
*/
else if (delay > params.mwDelayRestartMilliseconds)
{
session.send(prompts.sayYouveBeenAwayForSoLong);
session.send("Resetting session.");
//session.replaceDialog("*:/");
//session.endConversation(prompts.sayHiToBegin);
session.reset("*:/");
}
//Insignificant Delay
else
{
next();
}
}
};
return mw;
};
bot.use(checker({}));
/*
* Once we have some sort of user profile, this is where the bot begins
*/
//Cause of action model
var model = params.LUIS_SERVICE_JDBOT;
var recognizer = new builder.LuisRecognizer(model);
var dialog = new builder.IntentDialog({recognizers: [recognizer]});
dialog.matches('plead.original.answer',
[
function (session, args, next)
{
session.beginDialog('originalAnswer:/', {entities: args.entities || {}});
}
]);
dialog.matches('plead.divorce',
[
function (session, args, next)
{
session.send("OK, you need a divorce.");
}
]);
dialog.matches('draft.qdro',
[
function (session)
{
session.send("One day I'll be able to draft a QDRO for you.");
}
]);
dialog.matches('update.profile',
[
function (session, args)
{
session.beginDialog("userProfile:/Verify");
},
function (session)
{
session.send(prompts.askWhatElseCanIDoForYou);
}
]);
dialog.matches('show.menu',
[
function (session, args, next)
{
session.beginDialog('/menuInterface');
}
]);
dialog.onDefault([
function (session, args)
{
var config = {
prompt : prompts.askShowMenu,
helpMessage: "Say 'YES' if you would like to see a list of things I can do for you."
};
ConfirmDialog.confirm(session, config);
},
function (session, results, next)
{
if (results.hasOwnProperty("navigation"))
{
switch (results.navigation)
{
case "quit":
session.endConversation(prompts.sayHiToBegin);
break;
case "restart":
session.endConversation(prompts.sayHiToBegin);
break;
case "back":
session.send(prompts.howCanIHelpYouMessage);
break;
}
}
else if (results.response)
{
session.beginDialog("/menuInterface");
}
}
]);
bot.dialog('/recognize', dialog);
bot.dialog('/', [
function (session, args, next)
{
session.send(prompts.howCanIHelpYouMessage);
session.beginDialog("/recognize");
}
]);
bot.dialog('/menuInterface',
[
function (session)
{
//Main menu, so to speak
var choices = Object.keys(prompts.abilities);
//Util.cleanupSession(session);
//In case Microsoft's State Machine gets messed up, we can put in some dummy data to keep the
//program runnning.
if (!session.userData.userProfile) session.userData.userProfile = {};
console.log("app: *:/menuInterface: channelId (%s)", session.message.address.channelId);
console.log(session.message.address);
ChoiceDialog.choice(session, prompts.howCanIHelpYouMessage, choices); // session.userData.config.PromptChoiceOptions);
},
//Dispatch to requested function
function (session, results)
{
if (results.hasOwnProperty("navigation"))
{
switch (results.navigation)
{
case "quit":
session.endConversation(prompts.sayHiToBegin);
break;
case "restart":
session.endConversation(prompts.sayHiToBegin);
break;
case "back":
session.send(prompts.howCanIHelpYouMessage);
break;
}
}
else if (results.response.hasOwnProperty("entity"))
{
session.beginDialog(prompts.abilities[results.response.entity].dialogName)
}
else
{
session.replaceDialog("*:/menuInterface");
}
}
]
);