I made a Twitter chat bot using Python to answer my friends’ messages with Cat Facts.
By: Andres Aldape
Tags: Cats, Twitter, Python 3 Tutorial, Chatbots

Honestly its surprisingly simple to do once you actually know the proper steps. However I decided to write this to talk about how I did it, and showcase the mistakes I made along the way so anyone trying to do the same doesn’t repeat them and has a slightly easier time replicating it.

As far as WHY I actually wrote this app.

The child inside me saw an API that returned pure comedic potential in the form of feline factoids and couldn’t contain itself from hyper-fixating on harnessing its power…

Basically I just wanted to make my friends laugh for a couple minutes. And it was worth it.

So how’d I do it?

This guide is for Python 3. You can probably make it work with 2.7, but its up to you to modify the code correspondingly.

First things first. You need a Twitter Developer Account. If you don’t have access to the Twitter API, all of this is pretty much pointless.

You got one? Great!

Step One — Register your App

Use your newfound powers to create an App, and give it permissions to Read, Write, and Direct Messages.

Then in the “Keys and Tokens” tab generate your Consumer API Keys, and Access Token keys.

Make sure to write them down. These Keys are vitally important in order to do this so double check you wrote all of them down correctly.

After you’re done with that, you want to create a Dev Environment with the app you just created registered to it.

Take note of the Dev Environment Label you put in. You are going to need it later on.

Mistake #1 — Please use the Account Activity API for this.

(Feel free to skip this.)

Originally when I started this project, I actually made a fully working application that used Tweepy, and Polling to work. This meant, however, that my app would not be able to react to Direct Messages instantly. Which, as I’m sure you can understand, isn’t great when you’re making a Chat Bot. (Even if its purpose IS sending useless, yet interesting information about cats over the internet)

The obvious solution for this is using Webhooks instead! And thats exactly what the Account Activity API does.

This way you don’t have to keep asking Twitter’s API over and over if there’s any new messages. They will just send you a POST request when there’s any activity on the account you’re subscribed to.

Step Two — Write a Webhook that follows Twitter’s guidelines

This is where the real fun begins.

In order to start receiving information from Twitter, so we can start working on our app, we are going to need to set up our Webhook, register it, and subscribe an account to it.

To do this, first of all, I recommend making a new folder with the name of your app and creating a Virtual Environment to work on, by running this in a command line at your project’s directory:

#For Windows

> py -m venv venv

This just makes things so much easier to manage. Plus this way you avoid messing around with documents outside the project folder. So you have your own little TwitterBot bubble to work in.

Now just activate your environment with the command

#For Windows

> venv\Scripts\activate #OR if you're using bash

$ source venv/Scripts/activate

Your terminal should end up looking something like this:

What’s important is that you can see “(venv)” part.

If you can’t, you are probably doing something wrong.

From here there’s a decision that you have to make:

In this guide I made the app using Flask, used Gunicorn as my server, and Deployed it to Heroku. I also used a couple more libraries to do certain jobs easier (as I’ll try to explain later on). So do keep in mind that depending on what libraries you want or plan on using, this is where things might start to change a bit codewise.

If you plan on following exactly what I did however here is what you need:

> pip install flask

> pip install gunicorn

> pip install python-decouple

> pip install tweepy

Flask is what we will use to actually make our API that will receive and react to information sent by twitter.

Gunicorn is to run the server on our local machine (for testing) and Heroku.

Decouple just simplifies the use of environment variables in our code. Which becomes relevant later on as you’ll see.

and finally Tweepy is the library we will use to actually send the direct messages.

Now with that out of the way. Lets start by actually writing our webhook using Flask.

Twitter’s Account Activity API has it so that in order to register your webhook, it has to pass what they call a “crc_challenge”. CRC stands for Challenge-Response Check.

What this means is that when you register your webhook they will first send a GET request with a “crc_token”as a parameter in the url. You must then hash this provided token with the “consumer_secret” you previously wrote down using HMAC SHA256, encode it in base64, and finally return the generated string as a response. If your response is correct you end up with an authorized webhook to which they will send the data you want using a POST request.

Yeah. Don’t worry about it you can just copy and paste the following code to your app.py and you should be golden.

If you wish to test this before we continue, create a .env file where you write down the keys you generated when you created your twitter app as environment variables. Like so:

consumer_key= YOUR-CONSUMER-KEY consumer_secret=YOUR-CONSUMER-SECRET access_token=YOUR-ACCESS-TOKEN access_token_secret=YOUR-ACCESS-TOKEN-SECRET

After that you can just run the app locally with:

> py app.py

You should be able to access it with your browser, or making a GET request to http://127.0.0.1:5000/webhook/twitter?crc_token=foo using something like Postman.

This should return a JSON response similar to:

{

"response_token": "sha256=x0mYd8hz2goCTfcNAaMqENy2BFgJJfJOb4PdvTffpwg="

}

Step 3 —Deploy your app, and register it to a user’s activity

Up next lets go ahead and host our app on Heroku.

If you don’t have a Heroku account, now’s the time to create one. I’ll wait.

Good to go? Perfect.

In order to deploy our app there’s a couple of things we need to do first —

With your text editor create a file called Procfile. and write the following:

web: gunicorn app:app

This file is what Heroku will use as a guide to actually run your app on their servers.

2. Next, you need to create a requirements.txt file that will tell Heroku which dependencies your app needs to run. To do this just run:

> pip freeze > requirements.txt

3. Finally create a .gitignore file, that will avoid you uploading some files you don’t need on the deployed version, and are just in general a bad practice to have online anywhere:

venv/

.gitignore

.env

__pycache__/

Note: Normally Procfile, and requirements.txt should also be in this file. However these two are necessary for Heroku to run correctly.

Click on New > Create new app, and name it whatever you see fit.

Click on the Deploy tab.

Follow the instructions Heroku provides, and launch your app.

Write down your app’s domain. e.g. “https://your-app-name.herokuapp.com”

Following this, back at our terminal we need to declare our environment variables inside Heroku itself.

In order to do this just run the command:

> heroku config:set consumer_key=YOUR-GENERATED-CONSUMER-KEY

This applies for all of your generated information. Meaning your consumer_key, consumer_secret, access_token, and access_token_secret

The reason why we are doing this is that we do NOT want that information hard-coded in our deployed app, since its a huge security flaw and with those keys anyone would have the ability to perform actions as you on Twitter. Which is no bueno.

Next up we need to register your Webhook.

In order to do that we need to send a request to Twitter’s API and with an authorized OAuth 1.0 session, and tell them to remember your specified endpoint.

We also have to register your account’s activity to the Webhook, with the same OAuth 1.0 session since the keys are the same for you and your app.

Don’t you fret. Here is a python script that will get that done for you:

Note: You don’t have to deploy this. This is just a tool I made to make it easier.

If you want to register someone else’s activity to this however, you will need to do a different authentication procedure called “Three legged authentication”, which you can find here:

Assuming everything was done correctly, you should now be the proud owner of a fully working Webhook, that is subscribed to the activity of your personal Twitter account!

Now lets have some fun with it.

Mistake#2 — Don’t try to send the request manually. (Again, you can skip this.)

This is probably the mistake that made me lose the most amount time.

Some of Twitter’s documentation can be somewhat confusing if you’re inexperienced on all the technical stuff surrounding HTTP Authorization procedures. So this led me to actually try and manually hash generate my own authorization keys to use in a CLI curl command.

Not my brightest moment. I’ll admit.

On the bright side, while falling down that particular rabbit hole, I learned a lot about how OAuth 1.0 and a couple of hashing algorithms work.

Step 3 — Finally use the information Twitter sends you as you see fit. (Or engage in some high octane feline shenanigans)

From here you’re pretty much home-free, you just need to set up a method that receives POST requests, and use the information you’re provided however you like.

Before we are done here though I would not be much of respectable guide if I didn’t show you one last thing, and that is: How to authenticate the incoming POST requests to make sure they’re from Twitter, and not some stranger on the internet trying to mess with your app.

Twitter actually provides us with the tools to do this.

In the Headers of every POST request they send, there should be an item called “x-twitter-webhooks-signature”.

You use this string to compare it to an HMAC SHA256 hash between your consumer_secret, and the POST request’s body.

Again, don’t worry. I got you covered:

Finally, if you’re still here and are wondering about the “Cat facts” part:

You have impeccable taste and don’t let anyone tell you otherwise.

Here is what you need to do:

In the “Do whatever you like” part of the above code insert the following:

Then at the top of your app.py, right over the line “app=Flask(__name__)”, add the following:

import re

import api_config

import catfacts api=api_config.create_api()

Finally just add these two files to your deployed app and voilà:

Here is the GitHub Repository of my finished version. In case you still have questions and/or I failed to mention something that has caused you to get stuck:

Also if you wish to actually test it out and see for yourself if it actually works feel free to DM me on Twitter! (And hey maybe drop a follow or something if you’re into that sort of stuff I don’t know.)

https://twitter.com/_quantumRaven