Posts tagged with "node.js"

Dynamic Bot Dialogs

Please note that this article’s age is showing as it’s talking about Bot Framework v3. The subsequent version of Bot Framework works entirely differently.

I’m having a lot of fun developing against botbuilder - the Node.js SDK for the bot framework.

When you’re learning to make bots, you study and build a lot of simple bots that do very little. In this case, it makes good sense to simply define the bot’s dialogs in the same file where you do everything else - the file you may call server.js or app.js or index.js. But if you are working on a bot with enough complexity or bulk to the dialogs, you’ll want to settle on a pattern.

Encapsulated Dialogs

The first pattern embraced I learned from @pveller‘s excellent ecommerce-chatbot. In fact, I learned a lot of good patterns from this bot.

In the ecommerce-chatbot bot, Pavel breaks each dialog out into a separate JavaScript file and wraps them in a separate module. Then from the main page, he calls out to those modules, passing in the bot, and “wires up” the dialog to the bot within that separate module.

Notice in the following code that the main app.js file configures the dialog by requiring it and then calling the returned function passing in the bot object. That allows the dialog to use the bot internally (even though it’s a separate module) to call bot.dialog() and define the dialog functions.

//simplified from https://github.com/pveller/ecommerce-chatbot

//app.js
...
let showProductDialog = require('./app/dialogs/showProduct');
...
intents.matches('ShowProduct', '/showProduct');
...
showProductDialog(bot);
...

//sampledialog.js
module.exports = function (bot) {
bot.dialog('/showProduct', [
function(session,args,next) {
//waterfall function 1
},
function(session,args,next) {
//waterfall function 2
}
]);
}

The result is a much more concise app.js file and a bit of welcome encapsulation. The dialogs handle themselves and nothing more.

Dynamically Loaded Dialogs

Later, while I was working with Johnson and Johnson on a bot, I developed a pattern for dynamically loading dialogs based simply on a) their presence in the dialogs project folder and b) their conformation to a simple pattern.

To create a new dialog, then, here’s all I need to do…

module.exports = function (name, bot) {
bot.dialog(`/${name}`, [
function (session, args, next) {
session.endDialog(`${name} reached`);
}
]).triggerAction({matches:name});
};

The convention I need to follow is to define a module with a function that accepts both a name and a bot object.

That function then calls the dialog() method on the bot just like before, but it uses the name that’s passed in as a) the dialog route and b) the trigger action. This means that if the dialog is called greeting, then it will be triggered whenever an action called greeting fires.

So far, this is a small advantage, but look at how I load this and the other dialogs…

getFileNames('./app/dialogs')
.map(file => Object.assign(file, { fx: require(file.path) }))
.forEach(dialog => dialog.fx(dialog.name, bot));

The getFileNames function is my own, but it simply reads the path you pass in recursively returning all .js files.

The .map() calls require on the path of each found file and adds the resulting export (in our case here the modules are exporting a function) to the array as a property called fx.

Finally, we call .forEach() on this and actually execute the function. This configures the dialog for our bot.

The overall result then is the ability to add dialogs to the bot without any wiring. You just create a new dialog, give it a filename that makes good sense in your application, and it should be loaded and ready to be targeted.

You may not get enough context from these snippets to implement this if that’s what you want to do, so check out a fuller sample in the botstarter repo that @danielegan is working on. The botstarter repo is designed to be a good starting point for creating bots.

The Regatta Project

My role at Microsoft is that of an evangelist, and that implies that we speak broadly to audiences about technology. Recently, however, my team is working one-on-one with organizations on exciting new Microsoft technologies - making sure they’re exactly what developers need.

One of the projects I’ve been working on recently is called Regatta championed by Baiyin Zhou (@baiyinvc) from Boston.

This entire idea is super fun. Imagine exercising on a rowing machine in a studio in a group session. Now imagine a visual on the wall depicting your rowing machine and those of the other session participants as real boats. As you heave and ho, you see your little boat moving across the screen.

There are just so many awesome scenarios that are possible at this point.

The visual of the boats alone is encouragement for you to work harder to compete against others in the class. But that’s pretty obvious isn’t it. What about the less obvious scenarios? What about being able to add in a phantom boat that represents the group’s average from yesterday’s workout? Now you’re not competing against your fellow rowers - you’re competing with them. You have to beat that phantom boat!

As soon as things in the real world - like our efforts to stay in shape - are digitized and turned into data, we get to do things like capture our progress, integrate with other fitness tracker systems, or even do data analysis to determine some deep learning from it.

This is the type of concept where digital systems really have an opportunity to affect our lives for the better. I keep saying that technology is not so interesting unless it improves our lives. For being such a technophile, I’m actually quite the skeptic, because all too often technology just gets in the way.

The Regatta Project envisions a future with a whole lot of rowing machines deployed with smart devices (the Raspberry Pi Zero at this point) attached to them, and assuring good communication with all of these devices is a great job for Azure IoT Hub.

Go check out the details of the [Regatta](https://microsoft.github.io/techcasestudies/iot/2016/12/10/regatta.html) project and let me know what you think with a comment below.

Regatta Architecture

The Simplest Node Website

I’ll start with the code…

require('express')().get('/',function(req,res){

res.send('hello world');

}).listen(3000);

There it is. The simplest Node.js webserver/website. Three lines of code.

I know I’ve got it a bit mungled together. I’m not recommending this code. Just having fun.

Notice that I’m hanging a () directly off of the require('express'). The require statement returns a function. This is one of the most popular of the Node module patterns. Since it returns a function, hanging parenthesis off of it executes the function.

The execution of the function returns an express app, and the app supports chaining like jQuery or LINQ, so you do a .get() and then a .listen() and those are both methods of an express app.

The .get() creates the root route ('/') and then allows you to provide a function to handle that route. The function does a simple hello world.

The .listen() starts up the engine.

After creating a JavaScript file called app.js with this content in it, just type node app, and you should get zero feedback. But then hit http://localhost:3000 in your browser of choice and you’ll get the reassuring “hello world”.

By the way, if you’re using ES2015, that gets even shorter…

require('express')().get('/',(req,res)=>res.send('hi')).listen(3000);