Playing with Azure Functions (Part I): Creating a Slack bot

Past March, Microsoft launched the preview of Azure Functions, often referred as an Amazon Lambda competitor.

This being my first post about this topic, I will briefly introduce Azure Functions and show how to create a simple bot for Slack with Azure Functions.

In the following posts, I will dive into more advanced features.

Basic Concepts

Azure Functions is a way of running code in the cloud without having to think of stuff like infrastructure or scalability.

It’s designed to be a fast development, fast deployment technology for an event-driven world. Therefore, in Functions we configure triggers for events and then Functions are executed based on them.

You can write code in the most common languages, such as C#, Node.Js, PHP, Python, Bash or Powershell.

And coolest of all, you only pay for what you use.

Creating my first function

Creating a function is super easy.

In this simple walkthrough, you will be creating a Bot connected to Slack.

Access your Azure Portal (if you don’t have a subscription, you can create a trial here) and create a new Function App.

image

When configuring the Azure Function, one thing to notice is that you can choose between a Classic or a Dynamic App Service plan. This is related to pricing.

On a Classic Plan, your function is regarded as a typical App, just like any other Web App in your plan. So, you don’t have any additional cost. On the other hand, the Dynamic Plan, enables you to pay on-demand, which means Azure provides and manages all the resources and you just need to pay the time that the code runs.

image

In this case, I opted for an already existing App Plan to save some money from my subscription.

When you access your Function App the first time, you can really see why this is a preview version, judging by the way it looks. Azure provides a quick start menu, that enables us to quickly create – what I presume to be – the most common scenarios for Azure Functions.

image

On the left panel, you have a shortcut to create a new function, which shows more options. Currently, Azure Functions leverages 8 different languages and has 45 available scenarios for development acceleration. But you can always choose to start from scratch with an empty template.

Choose the language C# and the Generic Webhook scenario from the dropdowns, rename the function to “HelloBot” and press Create.

image

On the Develop tab, you can see the code generated by the template, the Url of the function, a logging console and even test the function. The generated function for this template, receives an HttpRequestMessage expecting a Json message with “first” and “last” properties.

image

This code is ready to run, so before continuing, we can quickly test it by scrolling down to the end of the page and, using the test console, send a request with the following:

{
   "first": "Azure",
   "last": "Functions"
}

After pressing Run, the Output should be a 200 OK with the following body:

{ "greeting":"Hello Azure Functions!" }

You can also notice there was a new entry in the logs panel above, regarding this last invocation.

Creating an Hello Bot for Slack

In this section, we will edit the previous function and create a bot that answers to Slack messages posted in a Slack channel.

In first place, our function needs to be able to understand Slack messages. The Slack webhook message format is something like this:

user_name=tpo&token=SomeToken&trigger_word=googlebot%3A&text=sample+text&user_id=U2147483697&timestamp=1355517523.000005&channel_name=test&channel_id=C2147483705&team_domain=example&example=T0001

We need to change the code of the function to simply check if the message contains the word “Hello” and if it does, the function will simple answer “Good mooooorning Vietnam!”

using System;
using System.Net;

public static async Task<object> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"Webhook was triggered!");

    string formDataStr = await req.Content.ReadAsStringAsync();
    string[] array = formDataStr.Split('&amp;amp;amp;');
    
    if(formDataStr.ToLower().Contains("hello"))
    {
         return req.CreateResponse(HttpStatusCode.OK, new {
                text = $"Good mooooorning Vietnam!"
                });
    }

    return req.CreateResponse(HttpStatusCode.OK, new {
        text = $""
    });
}

Now we can test the function using the same method as before, but this time we will send a message containing the following:

user_name=tpo&amp;token=SomeToken&amp;trigger_word=googlebot%3A&amp;text=hello+my+friend&amp;user_id=U2147483697&amp;timestamp=1355517523.000005&amp;channel_name=test&amp;channel_id=C2147483705&amp;team_domain=example&amp;example=T0001

If we send a message not containing the word “hello”, the function should return an empty text message, which Slack will ignore.

Bindings

We are not ready yet.

As it is, our function is still expecting a Json message and Slack is sending messages in another format (you can try to hit your function using Postman and see the error message).

In order to change this, we need to access the Integrate tab, which is where we configure the bindings of our function. A binding is an abstraction so that the same code can be used to interact with different sources or outputs. Remember we chose a preconfigured scenario, which has two bindings: an Http trigger and an Http Output. I will leave more details about bindings for a dedicated post.

For now, just change the Http Trigger to “Standard” mode, instead of “Webhook” which only supports GitHub or Json at this point. You can leave the Authorization Level with “Function” or “Anonymous”.

Configuring Slack

On your Slack team, add a new Custom Integration called Outgoing Webhooks.

When configuring the Webhook, just copy the Url from the Develop tab of the Azure Function. If you notice, the url has a “code” element on the query string which is used for authentication purposes. You need to copy the full Url including that.

After configuring slack’s webhook, just go to the channel where you configured the webhook and write “Hello!”. Your bot should answer accordingly!

Leave a Reply

Your email address will not be published. Required fields are marked *