How to Build a Simple Slack Bot

Posted by Bob on Tue 04 April 2017 in Tools • 3 min read

I was playing with Slack's Real Time Messaging API the other day. Building a bot is pretty easy. In this article a simple example.

Bots are hot

This was an interesting coding exercise, but also keep in mind its relevance. Bots are hot, people have become comfortable with conversational interfaces.

some commands our bot listens to

(GIF made with 100DaysOfCode day 003 script)


Slack API

About Slack's Real Time Messaging API:

The Real Time Messaging API is a WebSocket-based API that allows you to receive events from Slack in real time and send messages as users. It's sometimes referred to as simply the "RTM API". It is the basis for all Slack clients. It's also commonly used with the bot user integration to create helper bots for your team.

Getting ready

Read here about Bot Users, you need to create a new bot user first. This will give you an API Token. Keep this private! I added mine to .bashrc to keep it out of version control. I retrieve it like this:

slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))

Secondly you need to pip install slackclient, I also used some other modules.

I took the starterbot code I found in this excellent article: How to Build Your First Slack Bot with Python. This made it a lot easier because it catered for all the initial setup, listening for mentions of the bot, intercepting targeted messages.

Only thing you have to do is to get the BOT ID and store it in your login script (in my case .bashrc):

$ python get_botid.py
Bot ID for 'pybitesbot' is XYZ

# .bashrc
export SLACK_BOT_TOKEN=ABC      # first step
export BOT_ID=XYZ               # as retrieved from previous command
export WEATHER_API=123          # used for one of the command scripts, see below

Bot actions

I wrote a bunch of scripts which respond to different commands, some also as part of our 100DaysOfCode challenge. I put them in the commands subdirectory. This structure makes it easy to add more commands over time.

In the main bot script I import all the commands:

from commands.mood import get_mood  # just a silly one
from commands.special import celebration
from commands.articles import get_num_posts
from commands.challenge import create_tweet
from commands.weather import get_weather  # bot reports more sun and later sunset Spain vs Australia (sorry Julian haha)

# and put them in a COMMANDS dict
cmd_names = ('mood', 'celebration', 'num_posts', '100day_tweet', 'weather')
cmd_functions = (get_mood, celebration, get_num_posts, create_tweet, get_weather)
COMMANDS = dict(zip(cmd_names, cmd_functions))

I then overwrote the (provided) handle_command function to have the bot respond to various commands.

def handle_command(cmd, channel):

    cmd = cmd.split()
    cmd, args = cmd[0], cmd[1:]

    if cmd in COMMANDS:
        if args:
            response = COMMANDS[cmd](*args)
        else:
            response = COMMANDS[cmd]()
    else:
        response = ('Not sure what you mean? '
            'I can help you with these commands:\n'
            '{}'.format('\n'.join(cmd_names)))

    slack_client.api_call("chat.postMessage", channel=channel,
                        text=response, as_user=True)

Lastly under main this starts the loop:

if slack_client.rtm_connect():
    ...

Deployment

And that's it for the code. On my server I run the bot with nohup to keep it running:

nohup python3 pybitesbot.py &

Update: I found an issue where the bot stopped working, so I added a little script (based on this SO answer) to respawn it:

$ cat slackbot.sh
cmd="$HOME/bin/python3/bin/python3.5 pybitesbot.py"
until $cmd; do
    echo "Slack bot crashed with exit code $?.  Respawning.." >&2
    sleep 1
done

$ ./slackbot.sh
StarterBot connected and running!

... pressing ctrl + c

^CTraceback (most recent call last):
File "pybitesbot.py", line 44, in <module>
    time.sleep(READ_WEBSOCKET_DELAY)
    KeyboardInterrupt

    Slack bot crashed with exit code 1.  Respawning..   => thanks for the shell script
    StarterBot connected and running!

# that was for demo, I still use nohup to leave the shell
$ nohup slackbot.sh  &

Result

And there you go ... as you can see we had some fun with it the other day :)

bot smart ass I

bot smart ass II

What's next?

Although this tutorial showed a simple deterministic bot, this really inspired me to think about ways we can make our pybitesbot smarter and help us automate tasks. Or what if we open up a Slack for our community and we have a bot helping people with common Python questions? That would be really cool!

I will do a part 2 when we have more progress in this space ...

The full code of the bot is here. We encourage you to fork it and start building your own cool bot (and tell us about it in the comments below).


Keep Calm and Code in Python!

-- Bob

>>> next(PyBites)

Get our 'Become a Better Python Developer' cheat sheet sent straight to your inbox by signing up for our Newsletter: