How to build your first slack bot in 2020 with Python & Flask using the Slack Events-API

How to build your first slack bot in 2020 with Python & Flask using the Slack Events-API

This blog was originally published at https://saurv-shrivastav.medium.com/

A few months back, I joined a Slack workspace community. As a starter project, I was required to build a Slack Bot. Now, the major problem that I encountered while building my first slack bot was that most of the articles and tutorials were quite outdated and I kept stumbling into petty issues while trying to work my way around. So, here I am presenting a simple guide on building your first Slack Bot.

Bots are a useful way to interact with various services such as Slack and Discord. Major organizations have begun to shift from the conventional mailing services to such platforms. Thus, building and using bots for completing random errands can be a major boost to your and your team’s productivity.

In this post, I will walk you through building a minimal Slack Bot with Python back-end. The idea is to set up a Slack Bot that will greet you back when greeted, once we have it up and running then we can extend the Bots ability just by coding additional logic. To know more about slack, Read this article.

The code for this tutorial can be found at this Github Repo.

Let’s cut the chase and begin working!

Step 1: Setting up Initial Requirements!

The requirements are as follows:

  1. A Computer in working condition XD

  2. A **slack account and a workspace** that you are part of.

  3. *Python 3.7 and above Follow this link to download Python for your operating system. You can refer to these tutorials on YouTube for the same — Windows, Mac-OS, Ubuntu (it’ll be somewhat similar for other Linux distributions).

  4. pippip has been included with the Python installer since versions 3.4 for Python 3 and 2.7.

Step 2: Establishing our Environment

virtualenv is a tool to create isolated Python environments. virtualenv creates a folder which contains all the necessary packages for your project. To know more about virtualenv, go here.

virtualenv can be installed by running the following command:

pip install virtualenv

Create a new directory (or folder) for the project. Go to the terminal (or Command Prompt on Windows) and change into the directory where you want to store this project. Within that directory, create a new virtualenv to isolate our application dependencies from other Python projects. This can be done by:

python3 -m virtualenv env

Activating the environment:

source env/bin/activate              (Linux/Mac-OS)

env/Scripts/activate                 (Windows)

Your prompt should now look like the one in this screenshot

Step 3: Create a new Slack App

Now it’s time to create the Slack App. Login with your credentials and you should see a screen like this.

Use “My Bot” as your App name (You can choose one of your choice). If you are signed into more than one workspace, pick a Development Workspace from the drop-down.

You’ll probably see a screen that looks something like the picture below, click on “OAuth & Permissions” from the left panel.

Scroll down to the “Scopes” section and click on “Add an OAuth Scope” under “Bot Scopes”. Add the following scopes from the list — chat:write, im:history, app_mentions:read and channels:history (These may be different based on the type of application that you are trying to build).

Next, move to Install App from the side bar navigation and click on Install App to Workspace.

Once the App is installed, it displays a ‘Bot User OAuth Access Token’ for authentication as the bot user.

Copy your app’s Bot User OAuth Access Token and add it to your python environmental variables. Back in your terminal, export the Slack token with the name SLACK_BOT_TOKEN:

export SLACK_BOT_TOKEN=YOUR-BOT-TOKEN-HERE             (LINUX)
set SLACK_BOT_TOKEN=YOUR-BOT-TOKEN-HERE                (WINDOWS)

Next, go back to your app’s Basic Information page

Add your app’s Signing Secret to your python environmental variables. In your terminal -

export SLACK_SIGNING_SECRET=your-slack-signing-secret-here

That’s it with slack for now, it’s time to code!

Step 4: Coding the Bot

It’s time to write the actual code that will do the magic! Create a file named bot.py inside the main folder. The project structure now looks like —

|-Slack-tutorial
    |-env
    |-bot.py

Type in the following code in bots.py -

from flask import Flask, Response
from slackeventsapi import SlackEventAdapter
import os
from threading import Thread
from slack import WebClient


# This `app` represents your existing Flask app
app = Flask(__name__)

greetings = ["hi", "hello", "hello there", "hey"]

SLACK_SIGNING_SECRET = os.environ['SLACK_SIGNING_SECRET']
slack_token = os.environ['SLACK_BOT_TOKEN']
VERIFICATION_TOKEN = os.environ['VERIFICATION_TOKEN']

#instantiating slack client
slack_client = WebClient(slack_token)

# An example of one of your Flask app's routes
@app.route("/")
def event_hook(request):
    json_dict = json.loads(request.body.decode("utf-8"))
    if json_dict["token"] != VERIFICATION_TOKEN:
        return {"status": 403}

    if "type" in json_dict:
        if json_dict["type"] == "url_verification":
            response_dict = {"challenge": json_dict["challenge"]}
            return response_dict
    return {"status": 500}
    return


slack_events_adapter = SlackEventAdapter(
    SLACK_SIGNING_SECRET, "/slack/events", app
)  


@slack_events_adapter.on("app_mention")
def handle_message(event_data):
    def send_reply(value):
        event_data = value
        message = event_data["event"]
        if message.get("subtype") is None:
            command = message.get("text")
            channel_id = message["channel"]
            if any(item in command.lower() for item in greetings):
                message = (
                    "Hello <@%s>! :tada:"
                    % message["user"]  # noqa
                )
                slack_client.chat_postMessage(channel=channel_id, text=message)
    thread = Thread(target=send_reply, kwargs={"value": event_data})
    thread.start()
    return Response(status=200)


# Start the server on port 3000
if __name__ == "__main__":
  app.run(port=3000)

Step 5: Subscribing to events

In order for Slack to contact your local server, you’ll need to run a tunnel. We recommend ngrok or localtunnel. We’re going to use ngrok for this example.

If you don’t have ngrok, download it here for your Operating system.

What exactly is ngrok? - ngrok is a multi-platform tunneling, reverse proxy software that establishes secure tunnels from a public endpoint such as internet to a locally running network service while capturing all traffic for detailed inspection and replay.

Image Source: https://ngrok.com/Image Source: ngrok.com

Run the script bot.py in a terminal window —

python3 bot.py

Yayyyy, it runs 😍 !!

You’ll require 2 terminal windows for this step. In a new terminal window run ngrok on port 3000 by typing in the following command:

ngrok http 3000

The terminal will then turn into some goofy window (just kidding)

Copy the HTTPS URL, It is- a59c33783408.ngrok.io in the above screenshot. You’ll need to have your server and ngrok running to complete your app’s Event Subscription setup. It’s time we get back to slack. Navigate to the Event Subscriptions section from the left pane. Toggle the Enable events switch to ON. Add your Request URL (your ngrok URL + /slack/events)

Lastly, scroll down to subscribe to direct messages. This is achieved by adding message.im, app_mention & message.channels events to bot events.

Save the changes and we’re done!!!!!! Once your app has been installed and subscribed to Bot Events, you will begin receiving event data from Slack! 🎉

Step 6: Go Ahead and interact with the bot

Invite your bot to a public channel, then say hi and your bot will respond!

Hurray, we see the bot responding to the hi message of the user. Now, you can play around with the code and write the logic for other events you want to support.

Complete Code of the above sample app can be found **here**.

Note: Please do not push your code into any public repository with private information like tokens or secrets stored in it. Ideally these values should be exported as environment variables.

To know more about my professional life, check out my LinkedIn. Find me on Github. Happy reading!

Did you find this article valuable?

Support Saurav Shrivastav by becoming a sponsor. Any amount is appreciated!