Microsoft Bot Framework is a solution that enables programmers to create quite interactive bots in other way, than manually parsing messages from user and reacting for them.
One of the recent request was to implement bot, that will react to the events by writing to the particular user. To be more precise – we are looking for the solution that will help in time logging – when event in Outlook Calendar ends, we want to get proactive message from the bot that will assist in logging time. Quite easy, right?
Bot functionalities. How to achieve impossible?
Ok, so implementation should be quite easy – there supposed to be some kind of webhook on the Outlook side that will trigger some action when event ends. Or at least when event starts (reminder). So let’s see, how the Outlook API works:
So far so good. We need some authentication token, that’s obvious, and call endpoint to create webhook – works like any other webhook anywhere. So let’s see, about what we can get those notifications:
Ok, so we have a problem… It seems, that all of the webhooks are about Create, Update and Delete actions. So there is no way to subscribe for notifications. That can’t be true! Maybe there is something about “reminders” in the documentation? Oh yeah, there is. Option to GET reminders from the specified start and end times. Completely useless.
So what are the options? Let’s say, that we can track all the changes, so we could react to newly created events. So we can assume, that we have list of events that needs notifications when event ends. But how can we trigger that at particular time?
We would rather like to avoid old school web applications with some kind of schedulers, especially, because information that we want to send and that functionality is quite small. We only want to start dialog with the bot, that will be hosted somewhere else. So what about Azure Functions?
Azure Functions is Microsoft answer for the need of the serverless functions that in theory should be responsible for single action (it’s very similar to the Lambda functions on the AWS)… As instance of the function is really small, they can be easily scaled in the Azure Infrastructure to fulfill nearly any demand. And it’s quite cheap to use them. And they can be created in many languages.
So let’s see, what the triggers are:
Looks good. As we need to trigger something at specific time, let’s see, how “timer trigger” works:
There is a schedule with CRON expression. What is CRON expression? It defines time (or timespan), when function should be called. Every digit (or as in those example – numbers and stars) mean something, like minutes, hours, day of month, month, day of week and year. So we can schedule some timer to trigger action every day at 5PM, or we can define to trigger every hour (*/1 from the example). But, those trigger is for the whole function, and it would be just silly to create new function for every calendar event. It would be also silly to trigger this function for example every minute to check, If any user requires notification. So let’s look somewhere else.
What about “Queue trigger” in that case? Maybe we could just throw all of the events to the queue, and “make them” execute at particular time? Documentation of Queues is quite spare, but there is one particular interesting property mentioned named “visibility”. So we could add event to the Queue when “create” webhook is triggered, and set visibility for the amount of time enough, to become visible when event ends. Bingo!
Basics (app registrations, overview of options)
Bot implementation changed a little bit recently. Previously You need to create bot account on the dev.botframework.com, and from there point to the web application, where bot itself was hosted. Now both of those things can be done from single place, as registration on that page points directly to the Azure Portal, so the Azure account is required, even if you plan to host your bot app on AWS. There are couple new options:
Web App Bot option creates everything that you need to create advanced bot, as it creates Web Application that can be as complex as you want:
- Bot Channels Registration is basically the same option as it was before – you need to manually create bot instance and in that channel registration you need to provide endpoints of that bot.
- Functions Bot – it’s rather self-explanatory – bot as Azure function, with all of its strengths and weakness.
In this case we will use Web App Bot (or Bot Channels Registration with the bot deployed on the Azure – it’s the same thing 😊).
Architecture of the solution
Let me describe workflow of the whole application. Center part of the application is “Bot Framework App”. It’s and web application that implements bot functionality, as well has some views, actions and callback handlers for logging in to the O365 account (to access the calendar) and receiving calls from webhook.
Main of the logic that is (or can) be shared between Bot Application and Bot Azure Function is stored in “Common Services”. Right there is logic that handles database and Queue Storage. There is also service that can initiate dialog between Bot and the user on Microsoft Teams.
About Microsoft Teams – that’s our main target for the bot. By default there is also Web Client enabled – other channels can be enabled as well, like Cortana or Skype.
First, user needs to login to O365 account so bot could get access Token (with the Refresh Token – important!), and the Teamwork API access key. That values are saved in the database, along with information about current channel/user – we need to be able to continue that conversation even outside of the context (proactive messages). At the same time, as soon as token is obtained, subscription for the Microsoft Graph webhook is also created.
When the notification is received (blue path on the diagram), details of the event are downloaded (as the notification contains only details about subscription and type of change), and that details are saved to the Azure Queue Storage with visibility equals time difference between now, and the end of the event.
When entry on the Queue becomes visible (green path on the diagram), Bot Azure Function is triggered, and using that data from the queue, conversation (dialog) with the bot is restored. Thanks to that user can talk to bot about time entry details and finally – log the time. In this particular case information about project/task list/task is obtained dynamically and displayed in the form of clickable buttons, so everyone has data relevant only in their own context that is easily accessible.
After clicking the button value is selected.
In the next part there will be more detailed description of bot implementation.