/ Engineering

Create a chatbot with Slack and Botkit

Last week, Slack announced an $80M fund to invest in startups that build software with Slack integration. It also launched the Slack App Directory, which allow developers to upload Slackbots and Slack integrations. On the same day, Howdy, one of the start-ups Slack has already invested in, released a toolkit called Botkit which help developers to create Slack integration with Node.js. In this tutorial, we will use Botkit to create a slackbot.

Why Botkit?

Botkit is toolkit which handle all basic communication with Slack API such as authentication, sending and receiving messages. This save developers a lot of time and allow them to focus on implementing their idea.

Introducing "Slackbob"

At the end of this tutorial, you will create a slackbot which can chat with you. Let's call it slackbob!

Slackbob screenshot
Unlike the original slackbot which can only understand "Hello", slackbob can chat like a human.

Let's start now!

1. Create a bot in Slack

a) Login you Slack account and go to bot configurations page, enter "slackbob" in username field and click Add Bot Integration.
create bot

b) Next, you will be brought to a edit configuration page. Under Integration Settings section, there is a API Token. Copy it to somewhere and you will need it later. Fill in the form to customize your bot and click Save Integration.
customize bot

2. Download Botkit

a) Download Botkit via git

git clone https://github.com/howdyai/botkit.git

b) Go into botkit folder, install all required dependencies using terminal

sudo npm install

c) Run the sample code with

token=API_TOKEN node bot.js

where API_TOKEN is the API Token you previously copied.

d) Login your Slack, enter any channel and invite your new bot by saying

/invite @Slackbob

Now if you say

  1. @Slackbob Hello
  2. @Slackbob call me Victor
  3. @Slackbob who am I
  4. @Slackbob shutdown
  5. @Slackbob uptime

Slackbob will response you like this:

Chat image

3. Understand the Botkit

So far slackbob can only respond to 5 messages above. Before we make it to be a real chatbot, let's dive into the code and see how Botkit works. (If you just want a talking slackbot without understand the code, you can directly jump into section 4.)

Open bot.js file and you will see a lot of controller.hears() functions. In fact, hears() is a function provided by Botkit to listen messaging events based on matching keywords in message text and here's where we need to implement our code to make slackbob do what we want.

Here's a simple example of hears() function;

controller.hears('lunch','direct_message,direct_mention',function(bot,message) {
    bot.reply(message,"WOOO~ Let's eat!!");
});

From this example, if you say "@slackbob lunch", "@slackbob lunchtime now!", "@slackbob Go lunch together?"...whatever message containing "lunch", slackbob will reply you "WOOO~ Let's eat now!!". Let's see how it works.

There are 3 parameters in this function:

i) The first parameters is used to specify the keyword(s) matched to trigger this handler. It can be a String or array of String.

For example, if you pass an array like this:

hears(['lunch', 'food'], ...);

this function will be fired by both lunch and food keywords.

ii) The second parameter is to specify types of messages to trigger this function:

I've added direct_mention in this parameter so this function can be fired when I say "@slackbob lunchtime" in channel. But what if you also want slackbob to response to lunchtime @slackbob, you can add mention to this parameter:

hears('lunch', 'direct_message,direct_mention,mention', ...);

Here's the full list of parameter options from Botkit github:

EventDescription
message_receivedThis event is fired for any message of any kind that is received and can be used as a catch all
ambient Ambient messages are messages that the bot can hear in a channel, but that do not mention the bot in any way
direct_mentionDirect mentions are messages that begin with the bot's name, as in "@bot hello"
mentionMentions are messages that contain the bot's name, but not at the beginning, as in "hello @bot"
direct_message Direct messages are sent via private 1:1 direct message channels

iii) The third parameter is a callback receiving bot and message:

hear('lunch', 'direct_message,direct_mention', function(bot, message){
    bot.reply(message, "WOO~ Let's eat!!");
});

bot can be used to reply the received message using reply (message, 'response text') function.
Apart from that, bot holds functions and data of slackbot and joined channels.

You can also call Slack API Methods using bot.api object. For example, if you want to get all unarchived channels slackbob joined, you can use:

bot.api.channels.list({'exclude_archived' : 1}, function (err, res) {
    console.log(res);
});

** In Slack API, The term channels only refer to public channels. All private channels are called groups.

message contains data related to received message, such as channel id, sender id, message text, sending time... Here's the example content of message object:

{
  "type": "message",
  "channel": "U024BE7LH",
  "user": "R143CD7MP ",
  "text": "lunchtime now!",
  "ts": "1450416257.000003",
  "team": "F038DHKHK",
  "event": "direct_message"
}

4. Make slackbob talks like a human

So far, sample code only provide five handlers to understand five types of messages. We are going to delete all the pre-implemented hears() functions and add our own hears() function.

a) Delete all the hears() functions and add

controller.hears('','direct_message,direct_mention,mention',function(bot,message) {
})

The '' above allow slackbob to listen all the messages.

The final code should look like this:

var Botkit = require('./lib/Botkit.js')
var os = require('os');

var controller = Botkit.slackbot({
    debug: false,
});

var bot = controller.spawn(
  {
      token:process.env.token
  }
).startRTM();


controller.hears('','direct_message,direct_mention,mention',function(bot,message) {
})

Next we are going to connect a third-party clever bot inside function(bot,message){} callback.

5. Introducing Cleverbot.io

Cleverbot.io is free and open source cleverbot with node.js interface. We will hook it up with our slackbob.

Go back to terminal and download it via npm

npm install --save cleverbot.io

Next, login here to get a API User and API Key.

cleverbot.io screenshot

Go back to bot.js file,
Initiate a cleverbot object by adding this code snippet at the beginning of the code:

var cleverbot = require("cleverbot.io"),
cleverbot = new cleverbot('API_USER', 'API_KEY');
cleverbot.setNick("Bob");
cleverbot.create(function (err, session) {
    if (err) {
        console.log('cleverbot create fail.');
    } else {
        console.log('cleverbot create success.');
    }
});

Make sure to replace API_USER and API_KEY with API User and API Key you just retrieved from above.

Then, add a code snippet to hears() function:

controller.hears('','direct_message,direct_mention,mention',function(bot,message) {
    var msg = message.text;
    cleverbot.ask(msg, function (err, response) {
        if (!err) {
            bot.reply(message, response);
        } else {
            console.log('cleverbot err: ' + err);
        }
    });
})

This code pass the received message to cleverbot and then return the reply message from cleverbot to slackbob.

So the final code should look like this:

var cleverbot = require("cleverbot.io"),  
cleverbot = new cleverbot('API_USER', 'API_KEY');  
cleverbot.setNick("Bob");  
cleverbot.create(function (err, session) {  
    if (err) {
        console.log('cleverbot create fail.');
    } else {
        console.log('cleverbot create success.');
    }
});

var Botkit = require('./lib/Botkit.js')  
var os = require('os');

var controller = Botkit.slackbot({  
    debug: false,
});

var bot = controller.spawn(  
  {
      token:process.env.token
  }
).startRTM();

controller.hears('','direct_message,direct_mention,mention',function(bot,message) {  
    var msg = message.text;
    cleverbot.ask(msg, function (err, response) {
        if (!err) {
            bot.reply(message, response);
        } else {
            console.log('cleverbot err: ' + err);
        }
    });
})

Boom! You now have a new friend which can chat with you anytime!

Go back to terminal and run the code again with

token=API_TOKEN node bot.js

Go to slack and talk to slackbob. Enjoy the chat!