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.
- Python 2 or 3
- pip and virtualenv so we can handle Python application dependencies.
- Flask web microframework. Check out a few resources if you need a primer on Flask.
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:
- A free Slack account, plus a team you’re a part of and have API access to. If not, sign up for the Slack Developer Hangout team
- The official Python slackclient code library
- Slack API docs
- Slack API testing token
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.
Activate that environment with the following command.
Awesome. You should see something like this.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
- Add natural language processing (NLP) to the Python Flask web app
- Try a different Slack client or ditch the helper library entirely and use the Requests library to implement retry logic
- Write and customize a more complicated Slack bot
Happy Father’s Day everybody!