Building A Dad Joke SMS Slack Bot In Python

June 19, 2016
Written by

bloglead.001

Did you hear the preamble joke the guy told before showing you how to build a SMS Dadjoke Slackbot in Python?

A phone is lost in the jungle, and gets tangled in a thicket of vines. It sees a python and says “Hey can you cut me some Slack?”

[I’ll pause while you mentally prepare yourself for an onslaught of Dad jokes]

Our Dadbot will text you terribly awesome jokes when you @ mention it in its Slack channel. Dadbot will also drop a quality Dad joke in a Slack channel when you text a Twilio number. This is the power of the Slack API combined with the Twilio SMS API — Dad jokes abound.

What We’ll Need

My dad doesn’t go anywhere without cargo pants, extra napkins stuffed in his pocket, and a map. We will also need a few precious items before heading out to build Dadbot.

Twilio Developer Evangelist and lover of all things Python, Matt Makai has a step-by-step guide on setting up your virtual environment right here on his blog.

For the Slack side of things you’ll need the following:

For all things Twilio, you’ll need these two things:

 

Setting The Stage For Dad Jokes: Your Development Environment

Using Terminal, create a proverbial cargo pant pocket in which you’ll store your Dadbot project. Once you create that directory, create a new virtualenv to separate our application’s dependencies from any other projects you’ve got in the works.

virtualenv dadbot

Activate that environment with the following command.

Source dadbot/bin/activate

Awesome. You should see something like this.

VirtualEnvActivated

It’s time to get the slackclient API helper library installed so we can send and recieve messages from our #dadbot Slack channel. Here’s the pip command you run to install the slackclient, Twilio helper libraries, and Flask.

pip install slackclient twilio flask

Next, we’ll need to get an access token for our Slack team as well as our Twilio API credentials. Get ready to export some tokens.

Cutting Dad Jokes Some Slack: Using The Slack Web API

What’s the good of telling a great Dad joke if there’s no one around to hear it? Slack’s chat app will serve as our vessel for Dad jokes. They offer programmatic access to their chat app through a simple to use WebAPI.

Click here to sign up for a Slack account, create a team, or sign in to your trusty old Slack account. Once you’re all set up, scroll down the API page to Authentication and click “Generate Test Tokens.”

Pro Tip – You’ll need administrative privileges in the Slack team you generate test tokens for.

SlackGenerateTokens

We’ll have to check that our Python code has the green light to call the Slack API. To test that it’s authorized, we need to export our secret tokens (from both Slack and Twilio) as enviornment variables. We’ll export the token with the name SLACK_TOKEN

export SLACK_TOKEN='your slack token pasted here'

Sending Texts To Your Dadbot

If you don’t have a Twilio account, now would be a good time to sign up for a free account. We need to access the Twilio API to send and receive texts. If you’ve already got a Twilio account, go ahead and sign in. You’ll need to purchase a number you’ll use to send text to and from Dadbot. If you have an existing number you want to use, that works as well.

Buyanumber

Twilio is going to ask for a URL it can hit to send an HTTP POST request once an SMS reaches our Dadbot Twilio number. We have to solve what I call the “Zoolander Problem — our code is only accessible to our local machine. To provide Twilio a URL and solve the Zoolander Problem, we’ll use ngrok to expose our local web server through an accessible domain.

After you download ngrok, get it up and running with this command in terminal.

./ngrok http 5000

You should see something like this.

ngrok

Grab the forwarding URL, go to your Twilio Console, and paste the forwarding url plus “/twilio” in the “A message comes in” field. Keep that Forwarding URL handy because we’ll need it to handle some Slack details shortly.
dropngrokinforwarding

Next, we’re going to export our Twilio Account SID and Auth Token as environment variables. Head into your Twilio Console and copy down these two variables.

accountsidauthtoken

Make sure you’re not still in the Python REPL. Enter CTRL + d if you still are. Once you’re out of REPL, use the following command to export the variables.

import os
from flask import Flask, request, Response
from slackclient import SlackClient
from twilio import twiml
from twilio.rest import TwilioRestClient

Remember all those environment variables we exported earlier? The os module will pull the TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN and other variables we exported from the command line. The Flask class will instantiate our app, while request Response will give us the HTTP inputs and responses we need.

Let’s grab those environment variables and instantiate the Flask app alongside the Slack and Twilio clients.

@app.route('/twilio', methods=['POST'])
def twilio_post():
    response = twiml.Response()
    if request.form['From'] == USER_NUMBER:
        message = request.form['Body']
        slack_client.api_call("chat.postMessage", channel="#dadbot",
                              text=message, username=dadbot,
                              icon_emoji=':robot_face:')
    return Response(response.toxml(), mimetype="text/xml"), 200

We’ll be using the python command to test that our Dadbot is running smoothly, and to start a Flask server. To make this possible, add the following function:

* Running on http://127.0.0.1:5000/ (Press CTRL C to quit)
* Restarting with stat
* Debugger is active!
* Debugger pin code: 144-609-426

It’s that time. Text your Twilio phone number. You should see that your message has posted in the Slack Channel like so.

dadbotsayshi

That simple “hai” is a confirmation that your SMS has hit Twilio, triggered an HTTP Post request to your ngrok URL, ngrok forwarded the POST request to your local machine, and hit the dadbot.py file that’s running on your Flask server. This is the journey of a Dad joke.

Importing Your Favorite Jokes, Exporting Random Dad Jokes

No one wants to hear the same joke over and over again. Use the import random module to allow our app to make a random Dad joke selection from our list of Dad jokes that we’ll contain in myList. We need to edit some code so Twilio knows to print the selected random Dad joke in Slack.

Go back into your Dadbot.py file and add the following lines of code.

# -*- coding: utf-8 -*-

import os
from flask import Flask, request, Response
from slackclient import SlackClient
from twilio import twiml
from twilio.rest import TwilioRestClient

SLACK_WEBHOOK_SECRET = os.environ.get('SLACK_WEBHOOK_SECRET', None)
TWILIO_NUMBER = os.environ.get('TWILIO_NUMBER', None)
USER_NUMBER = os.environ.get('USER_NUMBER', None)
 
app = Flask(__name__)
slack_client = SlackClient(os.environ.get('SLACK_TOKEN', None))
twilio_client = TwilioRestClient()

import random
import random
myList = [“Your dad jokes here”, “even more dad jokes,”] 
random.choice(myList)


@app.route('/twilio', methods=['POST'])
def twilio_post():
    response = twiml.Response()
    if request.form['From'] == USER_NUMBER:
        message = random.choice(myList)
        print message
        slack_client.api_call("chat.postMessage", channel="#dadbot",
                              text=message, username='dadbot',
                              icon_emoji=':robot_face:')
    return Response(response.toxml(), mimetype="text/xml"), 200

We’re using the random.choice module to select a joke from myList and telling Twilio to print that joke in our Slack channel.

Save the dadbot.py file and try texting your Twilio number. It should print a random joke in your Slack channel.

Dadbotmakesajoke

My Dad thinks slack refers to rope and types emails in blue comic sans. It’s safe to say he’s not logging into Slack on a regular basis. Let’s open up the enjoyment of Dad jokes to him by triggering texts when you @mention dadbot in a Slack channel.

Receiving Slack Messages via SMS

In order to trigger a text when someone summons the dadbot, we need to use Slack’s outgoing webhooks. The outgoing webhook will alert our Python app through an HTTP POST Request.

CTRL+C that Flask server you’ve got up and running. We’re going to modify our dadbot.py file by adding the following highlighted bits of code.

# -*- coding: utf-8 -*-

import os
from flask import Flask, request, Response
from slackclient import SlackClient
from twilio import twiml
from twilio.rest import TwilioRestClient
 
SLACK_WEBHOOK_SECRET = os.environ.get('SLACK_WEBHOOK_SECRET', None)
TWILIO_NUMBER = os.environ.get('TWILIO_NUMBER', None)
USER_NUMBER = os.environ.get('USER_NUMBER', None)
 
app = Flask(__name__)
slack_client = SlackClient(os.environ.get('SLACK_TOKEN', None))
twilio_client = TwilioRestClient()
 
@app.route('/twilio', methods=['POST'])
def twilio_post():
    response = twiml.Response()
    if request.form['From'] == USER_NUMBER:
        message = random.choice(myList)
        print message
        slack_client.api_call("chat.postMessage", channel="#dadbot",
                              text=message, username='dadbot',
                              icon_emoji=':robot_face:')
    return Response(response.toxml(), mimetype="text/xml"), 200

@app.route('/slack', methods=['POST'])
def slack_post():
    if request.form['token'] == SLACK_WEBHOOK_SECRET:
        channel = request.form['channel_name']
        username = request.form['user_name']
        response_message = username + " in " +  channel + " says: " + random.choice(myList)
        twilio_client.messages.create(to=USER_NUMBER, from_=TWILIO_NUMBER,
                                      body=response_message)
    return Response(), 200

@app.route('/', methods=['GET'])
def test():
   return Response('It works!')
 
 
if __name__ == '__main__':
    app.run(debug=True)

Notice that random.choice(myList) addition in the response_message? We’ll be using that function again to trigger random Dad jokes via SMS.

Go to the Slack Outgoing Webhooks page then click the “outgoing webhook integration” link as shown below.

outgoingwebhooksclick

Head down to the Integration Settings section. Click “#dadbot” as the channel to listen on. Type “@dadbot” in the “Trigger Word(s)” value. Copy and paste your ngrok Forwarding URL plus “/slack” into the URL(s) text box.

generatedtoken

After you copy your Slack token, click “Save Settings”. I regenerated the token in the picture so it won’t work if you accidentally copy it. Export your Slack token as an environment variable using this command.

(dadbot)$ export SLACK_WEBHOOK_SECRET = 'generated outgoing webhook token here'

Restart your Flask server and prepare for awful jokes. We’re going to test out receiving messages from Slack via SMS. Head on over to the #dadbot channel you created. You should see the prompt that an outgoing webhook integration has been added to the channel.

outgoingwebhookadded

Try @mentioning dadbot. The message has to start with that @mention. My message to dadbot won’t work because I pre-empted it with “what’s up”. Try saying “@dadbot tell me a joke!” You should get a joke sent to your phone.

thedadjoke

Awesome! Our Dadbot lives and is telling a whole host of random, terrible jokes. Let us know what Dadjokes you equip your Dadbot with. My personal favorite is “What’s a vampire’s favorite fruit? A necktarine.” Yep. It’s awful. Don’t blame me, blame my Dad. It’s his joke. If you’ve lost your appetite for adding more jokes to your app, here are a few things you can do to expand on your Slackbot.

Happy Father’s Day everybody!