Bob the Twitter bot

Kristian Roopnarine
6 min readJul 22, 2019

--

Top-Down Design

For some odd reason I wanted to create a twitter bot that would post an inspirational quote everyday at 8 AM. I chose to use Python for this task because the language is known for it’s automation and I know there’s a library called Beautiful Soup that pulls information about web pages. I knew that would be handy in solving this problem so I started to break down the bot step by step:

First I’d need to open twitter and sign in.

Then I’d have to sign in.

After signing in I’d need to pull and save a quote from somewhere, either from a quote API or database that contains a bunch of quotes.

The bot would then have to check whether or not it is 8 AM, and if it is then post the quote to twitter. I would need to figure out how to run a Python script indefinitely even while my computer was turned off.

I translated this into a rough Python function called bob:

def bob():
twitter() #opens twitter
sign_in()
get_quote() #pulls quote and saves it
post() #checks time and if 8AM posts saved quote

This was generally how I thought the bot would run and I’d just put it in a infinite while loop to keep running.

Twitter()

Creating a function to open twitter was fairly simple. A module called webbrowser can be used to open a tab in your default browser with a given URL. The code for this was fairly simple:

def twitter():
webbrowser.open_new_tab('https://twitter.com/')

The next step is to find out how to locate the sign in text fields, username and password. Then use Python to input a given username and password into the fields to sign in.

Sign_in()

I started reading the documentation of the module Beautiful Soup to pull the HTML elements that contain the text fields for the username and password. Just like any programmer I took to google to find out if this has already been done. Lo and behold I find that there was already a module called Tweepy used in Python to create posts and access various Twitter features. This changes my original bob algorithm because it makes it much easier to access twitter. I don’t need different functions to open and sign in, I can do that all in one function now.

New Algorithm

With the module Tweepy now I can think of solving this bot a bit differently. I also thought it would be better to check the time first and then pull a new quote instead of the previous method of finding a quote, saving it then posting it.

The bot will have to access twitter.

Then it will check the time, if it is 8 AM it will pull a quote from somewhere and post it.

If it is not 8 AM do nothing and continue to check the time. I don’t want the bot to check the time frequently so I’d probably put a time.sleep() somewhere and make sure it’s under a minute.

I changed the bob function to this:

def bob():
access_twitter()
check_time()
post(quote_details)

Access_twitter()

Accessing twitter using this module was fairly simple. I had to change my twitter account to a developer account to get a consumer key and access key. Tweepy uses these keys to create an api object that is used to ‘speak’ with twitter. The code was fairly simple:

def access_twitter():
#creates an api object to interact with twitter
consumer_key = 'x'
consumer_secret = 'x'
access_token = 'x'
access_token_secret = 'x'
auth = tweepy.OAuthHandler(consumer_key,consumer_secret)
auth.set_access_token(access_token, access_token_secret)
global api
api = tweepy.API(auth) #using this api object to talk to twitte

I made the api object global so it can be used outside of the local scope of the function when the bot decides to post a quote.

Incorporating Unit testing

Throughout the process I tested each function as I made them individually to ensure that they worked. For the access_twitter function I made sure that I successfully connected to twitter by adding this line of code at the end:

api.update_status('Hello from Bob. Kristian's Twitter bot made using Python.') 

The api object is used to post a new status on my twitter account. I put this after the access_twitter() function to test if I was connected to the api successfully.

Check_time()

Now I needed my bot to be able to check the time and perform a task of posting quotes specifically at 8 AM everyday. For this I used the datetime module:

from datetime import datetime as dt

From the datetime documentation there were two methods that I thought would be useful. The

datetime.today()
datetime.strftime()

Datetime.today() returns the current local time and datetime.strftime() formats the time into a string based on the arguments. I thought I can use the datetime.today() to determine the current time and datetime.strftime() to format it into a string that can be used in an if statement. Together this will allow the bot to check whether or not it is 8 AM. This translates into the code:

def check_time():
#checks time and returns time string
when = dt.today()
global t
t = when.strftime('%H:%M %p')
return t

The arguments in the when.strftime() method format the time to 00:00 AM/PM. To test if this function worked as I intended I paired it with access twitter to make a post at a certain time which looked similar to this:

while true:
check_time()
if t == '19:00':
access_twitter()
else:
print(It's not time yet')
time.sleep(50)

The access_twitter function will only execute if the time was 7 pm and it was set to print the current time as a new twitter status. If not, the function slept for 50 seconds and printed to the console ‘It’s not time yet’ just to ensure that the code was working as intended. After this was working the next step is to determine exactly how to get a quote and posting it to twitter.

Post(quote_details)

The function will take the quote_details from the argument and post it to twitter only when it is 8AM. The post function will have to access twitter first then updated the status.

def post(quote_details):
access_twitter()
api.update_status('"%s." \n- %s. \n\nFrom Bob the Twitter bot' %(quote_details))

Fairy straight forward, when the function is called it will access twitters api and use that to update the status with the quote details. The ‘%s’ is used in Python for easy string formatting for the quote_details argument.

Quote_details / get_quote()

The quote_details argument will be a function that returns the quote and author of a random quote. I chose to pull the quote from theysaidso.com because they provide a free api that can be called 10 times an hour. You can select the category of quotes as well. The call returns a JSON and the quote details will be pulled and saved.

def get_quote():
#pulls quote from theysaidso.com
response = requests.get('http://quotes.rest/qod.json?category=inspire')

quote = json.loads(response.content).get('contents').get('quotes')[0].get('quote') # pulls quote from JSON

author = json.loads(response.content).get('contents').get('quotes')[0].get('author') # pulls author
return quote, author

Pulling the correct data from the JSON took a couple of trial and errors to use the right arguments for the .get() method. The function returns the quote and author which are used to update the status in the post() function.

Putting Bob together

I have all the different parts, a function to check time, a function to access twitter and post statuses, and a function to get random quotes. Now I had to make an infinite loop that continuously checks the time to determine when to post. I had an outline of this earlier but the outline would look like:

def bob():
while True:
check_time()
if t == '08:00 AM':
print(t)
post(get_quote())
time.sleep(61)
else:
print('It\'s not time yet')
time.sleep(50)

The time.sleep(61) was added after the if to ensure that after the bot posts a quote the next iteration of the while loop will proceed to the else block because the time will be at least 8:01.

I tested this function twice to ensure that bob logged to the console the time at two different instances. To make this script run indefinitely I created an account on Pythonanywhere.com and ran the script on their console.

Check out the daily inspirational quotes on twitter - kristianrxd.

--

--

Kristian Roopnarine
Kristian Roopnarine

Written by Kristian Roopnarine

Full Stack Engineer sharing tips and tricks for anyone learning to program. Connect with me on LinkedIn : https://www.linkedin.com/in/kristianroopnarine/

No responses yet