Creating a Twitter Bot using Google Cloud Functions

Start with a call to action

They told me to start with the most important thing someone should do after reading this post so, like, buy your mum some flowers. Maybe potted ones rather than cut ones. Turns out flowers and mums are both more important than marketing and Twitter bots.

Twitter bots

Some examples of Twitter bots include productivity tools, for instance the Thread Reader App and Read Later Bot make it easier to manage Twitter content.

They can also be a big part of political marketing (or you might say propoganda). It’s a common understanding that many of the accounts online advocating or criticising political points of view are actually automated mouthpieces. Whether these accounts are real people or not – we now understand that it’s easy to create an army to spread your message.

Better the devil you know

Given how powerful these tools are, I wanted to understand Twitter bots better. So, I made a Twitter bot and here I’m going to share how (that’s also a convenient way to turn my obsessive tinkering into something that sounds altruistic or wise).

I had a few criteria;

  • It had to work by itself without me manually running code
  • It had to run around the clock
  • It had to be free for me to run
  • It had to work entirely within Twitter without people having to log in somewhere else
  • It had to be easy for me to do.

The bot I made is called Monitor Name, I wrote a post explaining it here. It’s pretty simple – you give it a list of Twitter accounts to monitor and it tells you when they change their display name or profile picture.

In this post I’ll also give you details of another Twitter bot I created but didn’t release because it’s (quite deliberately) pure garbage and helpful to no one.

My bots are pretty simple but they’re an introduction to how people can automate Twitter interactions. That information can be useful for productivity and marketing, or to understand how others might create and manipulate similar programs.

Setting up a bot account

Start by creating a new Twitter handle

Assuming you don’t want everything to happen through your own Twitter handle, you’ll need to create a new account. It’s worth choosing a handle that’s descriptive of what you want the bot to do because that’ll help your future users. As a result, it’s worth sitting down before you do anything, and deciding exactly what you want your Twitter bot to do. There’s no point wasting your time filling the internet with more noise unless it’s going to help someone, somewhere and you’ll also save yourself a bunch of time and headaches by having a clear idea from the off.

Once you’ve got your bot’s handle set up, go to developer.twitter.com, log in with your new handle of choice.

Then create an app

In Twitter’s words, “Think of a Twitter app as a gateway” – it’s just a way to get Twitter to give you codes you need to interact with service as a machine.

Click the drop down on the right hand side, then apps. That’ll take you to the apps screen (below).

Click Create an app, which will take you to a form that you need to fill out (below).

Twitter says that your app needs to be approved before it will be live. That could make you think you need to make a strong case in this form, and that it’ll take a while to get approval. If so – prepare for a surprise. I’ve created a few apps using this form, each time they were approved within seconds, one of them I finished by accident because it was so easy to do.

What’s more, once your app is approved, you’ll be taken to the profile for that app, and from there you can edit all of the details you wrote down in this form.

It’s also worth taking the look at the developer terms and conditions that pop up along the way, they’ll clue you in to some of the snags you might hit. For example if you try to tweet the exact same text twice, Twitter will stop you from doing that to avoid you spamming.

You can edit the Twitter name and profile picture but if you’re only using this to create your own Twitter bot, you’re the only one who will see those things (everyone else will just see the profile picture and description you set in Twitter).

Change permissions

If, like me, you want your bot to be able to use DMs you’ll need to edit the permissions because they don’t include that by default. Click the Permissions tab in your app, then edit and select Read, write, and Direct Messages.

Get your keys and tokens

These are the details we actually need out of this. You’ll use them when you try to interact with Twitter using code. Click on the Keys and tokens tab and then click Create. Once you’ve done that, you’ll have four codes on-screen. Don’t share them with anyone but do keep them on-hand, you’ll need to use them with your code.

The keys and tokens screen. Quick note – do not share any of this with anyone unless you know exactly why you’re doing that (and you trust them to have complete control of the account).

All of these details will be useful when we’re writing our code so save them somewhere safe (or if you’re like me -. keep the tab open) so you can copy and paste them across when you need to.

Choose your library

Twitter lists a bunch of helpful libraries here. I used Tweepy – it was pretty easy to work with and Google Cloud Platform is able to install it without hassle.

Why Google Cloud is better than Lambda for this

We’re going to use Google Cloud as a way to run code independent of us. For anyone familiar with Amazon AWS – we’re going to be using Cloud Functions which is similar to running code through Lambda.

If you don’t need convincing to use Google Cloud rather than Lambda, feel free to skip to the next section, otherwise, here is why I much prefer Google Cloud over Lambda for this kind of thing.

Less important but still nice – authorisation

I’m using BigQuery as my database, to store lists of accounts which users want to follow. Because I’m using the same account through Google Cloud – I don’t have to worry about authorising changes every time I try to access it. Google handles that automatically.

Saving us from eternal hoop-jumping torment – using unusual libraries

When I’ve used Lambda to write simple Python that doesn’t rely on any more unusual libraries (like Pandas for example) Lambda has been a dream. I write the code, straight into the editor, I can test it with a press of a button, and I get nice, detailed error reports.

However, for this project, we do want to use a more unusual library – Tweepy – to handle our interactions with Twitter. That’s when things start to get complicated with Lambda.

Lambda won’t automatically install libraries for you, so to use them, you have to upload them, but it’s not that simple.

To upload libraries you have to upload everything (you’ll overwrite anything already there when you upload) so you’ll need to write your Python file on your laptop, save all the libraries you need to a folder and upload them all together. But it’s not that simple.

Because of the size of libraries it often means you are uploading more data than you can with the normal method, so Lambda will ask you to do it through the command line, which means you’ll need to learn (or more realistically, paste) the commands needed along with the specific ID of the function you want to update. To be fair instructions for all of that are available online. But it’s not that simple.

To upload through the command line you have to have security credentials for your AWS account to use. To set up the proper credentials you have to embroil yourself in AWS security and permissions setup to create security roles and whitelist IP addresses allowing them to make changes to your AWS account. When you’ve got all of that in place you can upload all of your files using the command line. But it’s not that simple.

You finally upload your functions, resist the urge to fist pump at the success message (ok, you fist pump a little) and then you get an error – “Invalid ELF Header”. It’s every bit as sinister as the pair below would have you believe

The horrors of Invalid ELF Header

Invalid ELF Header probably means that when you were setting up your code on your laptop, ready to upload it to Amazon, programs were making a bunch of decisions for you. For example maybe they were seeing that you’re on a Mac, so you need the Mac version of the libraries you’re trying to install, likewise for Windows.

Thing is – Amazon Lambda runs on a version of Linux, which means your libraries won’t work for it. Now you’re in a sticky wicket – you have to find some way to tell your computer to do the wrong thing now so it’ll be the right thing later. I am forever indebted to Liz Rice who wrote this post on freeCodeCamp explaining how to get around the ELF Header problem. You use Docker to install all the libraries in their own environment which is just like Lambda will be.

But isn’t this all just a colossal pain? It’s much easier with Cloud Functions so bear with the following steps, I think it’s worth it.

Setting up Google Cloud

Go to console.cloud.google.com/. If you have never used the Google Cloud console before, you probably haven’t set up any projects yet and you probably haven’t set up billing either. Fortunately, you should be able to just follow the prompts on-screen to do both.

When you first go to cloud.google.com you should be presented with a screen which walks you through setting up billing. If you don’t, and instead see the general screen, click on the “Activate” button in the top right hand corner (as you can see below). Afterwards Google will take you through the steps.

In case you’re worried about spending money on this Google lays out their pricing here. Google has a free tier which allows for code to be run 2 million times a month depending on your settings. They also offer $300 credit for any overspill. In short – it’s possible to be charged by accident, as with any of these things, but if we avoid trying to do really complicated things and trigger our code at certain times then we shouldn’t hit these limits. I’ll explain how we’ll manage the triggering later on.

Cloud Functions

Once you have billing set up you can create a project. Go to the Cloud Functions section.

As mentioned, cloud functions are kind of like Amazon’s Lambda. They’re a way for you to write out some code that will be triggered by some other criteria you set (more on that later) will do a thing, perhaps return a result, then stop.

Click to create a new function, you’ll be presented with a screen to fill out, but before we do that we’ll write out our Twitter bot so we can create it in one fell swoop.

If you do need to edit code after you’d created a function that’s also quite possible.

Writing our Twitter bot

Tweepy

Tweepy documentation is really helpful but we’ll go through some of it here too.

Tweepy auth

You should already have your Twitter credentials. Tweepy will need them to interact with Twitter. I recommend putting all of that information in your Environment variables. Scroll to the bottom of the page where you’re writing your Cloud Function, click the dropdown, scroll further and you’ll see where you can add your variables. The left-hand column is the name you’re giving a variable, you’ll use that to call the information later, the right-hand column is the information.

Click the dropdown to access the environment variable
Click to add environment variables

Once you have your variables in there, you can call them. The line below will get the variable you’ve called “consumer_key”.

os.getenv("consumer_key")

Tweepy has some simple code for you to set up authorisation using your consumer key and consumer secret. I use these lines to get Tweepy authorised to interact with Twitter

# Getting the key and secret codes from my environment variables
consumer_key = getenv("consumer_key")
consumer_secret = getenv("consumer_secret")
access_token = getenv("access_token")
access_secret = getenv("access_secret")


# Tweepy's process for setting up authorisation
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_secret)
api = tweepy.API(auth)

Tweepy will use that api variable whenever it tries to do something with Twitter so once you’ve run these lines it’ll have everything it needs to interact with your account.

Tweepy commands

Once you’re set up with authorisation, you can do things like post tweets to your timeline quite easily. For example, the below will tweet out the message “my tweet”;

api.update_status("my tweet")

This will retrieve all of the recent DMs sent to your account;

dms = api.list_direct_messages()

This will retrieve a list of the 20 most recent mentions;

API.mentions_timeline()

As mentioned before, the Tweepy documentation is really helpful it’s worth having a dig around that to see what you’d like to do.

Example Twitter bot

So we’ve said we’ll use Tweepy, we’ve got a couple of example commands above but what does it look like when we put it all together?

Below is some example code – it’s a Twitter bot. It’s also an automated time waster. It plays on the “OK boomer” meme by looking for tweets that mention words that sound like “boomer” and then replying to those tweets with the phrase. For instance it’ll find tweets that include “bloomer” and reply “OK bloomer”.

It’s not a helpful bot, it wouldn’t contribute positively to the internet if we set it off into the world but we can use it to understand how to make something better.

def send_tweet(request):

    # Importing the libraries we'll use
    import tweepy
    import os
    import random
    from os import getenv
    

    # Getting the key and secret codes from my environment variables
    consumer_key = getenv("consumer_key")
    consumer_secret = getenv("consumer_secret")
    access_token = getenv("access_token")
    access_secret = getenv("access_secret")


    # Tweepy's process for setting up authorisation
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_secret)
    api = tweepy.API(auth)


    # A list of words that sound like "boomer"
    oomer_list=["rumour", "bloomer", "humour", "puma", "fumer"]


    # For each work that sounds like "boomer"
    for oomer in oomer_list:
        
        # Search Twitter for tweets containing this word
        oomer_search = api.search(q=oomer)
        
        # Select a random tweet from the list
        random_oomer = random.choice(oomer_search)
        
        # Get the text of that tweet (we're only doing it so you can see it if you want to)
        random_oomer_text=random_oomer.text
        
        # Get the ID of the tweet (we need this to send a response to the tweet)
        random_oomer_id=random_oomer.id

        print (random_oomer_id, ">>>", random_oomer_text,"""

            """)
        
        # Creating the message you want to send
        message = "OK {}".format(oomer)

        
        # Sending the message using the status id to reply
        api.update_status(message,in_reply_to_status_id=random_oomer_id, auto_populate_reply_metadata=True)

Requirements

As mentioned above, we can just write out our requirements to Google Cloud and have it install those libraries – that makes our lives way easier. In our code we’re using tweepy to interact with Twitter. We also use random to choose random items from a list and os to get our environment variables. However, random and os are included in standard Python so our requirements.txt looks like this;

# Function dependencies, for example:
# package>=version
tweepy

When we save the code, Google installs these libraries, so that when we call them (a la the below) the whole operation won’t throw a hissy fit.

# Importing the libraries we'll use
import tweepy
import os
import random
from os import getenv

Setting up our Twitter bot in Google Cloud

The create function screen includes all the fields we need to fill out to get started. Below I’ll write out the instructions alongside each part of that screen.

Give the function whatever name you like as long as it’s memorable, I’m calling it ok-boomer. What we’re doing isn’t processing-intensive so we can leave the allocation at 256MB.

The trigger field is how your function will be activated. For our purposes we could use a few different trigger types but to keep things easy let’s leave the trigger as HTTP.

We’ve written it in python so we’ll select Python 3.7 as the language and Inline editor under Source code. Then we paste the Python we wrote straight into the screen.

We need to make sure we include all of our requirements, so we click the “requirements” tab and paste in the below

import tweepy
import os
import random

The way we’ve written our code, we’ve called the function send_tweet so we need to write send_tweet in the function to execute field. That just means when this Cloud Function gets activated it’ll run the send_tweet function.

At the bottom of the screen there’s a drop down button that will reveal the environment variables and you need to fill them out as we said before – using the details we got from Twitter.

Then we hit Create. You’ll be dumped back at the function listing screen and when everything is loaded properly. When everything is saved you’ll get a little green tick next to your newly listed function.

Testing your Function

Click on your function and you’ll be taken to the General dashboard. When your function is running the graph will show you all the times your function has successfully and unsuccessfully run.

The orange dashes show where the function has been activated

Click on the testing tab, it’ll look kind of weird and empty but don’t worry, you don’t really need to fill it out. All you need to do is click test the function. If it runs fine it’ll finish with an output like “OK”.

Editing

If your function isn’t working and you need to change it, or if you want to change functionality, then you can access your code to make changes by hitting the edit button. Once you’ve finished making changes you just need to hit Deploy to save your changes.

Word of warning – wait a couple of minutes after you deploy changes before you test it again. Otherwise, you’ll just be testing your old code.

Scheduling your function

Now that we have code that runs, we want to make it so that it runs without us. You may remember, we set our function trigger to HTTP. That means when something makes a request to a dedicated URL, your code will be activated. To get your url, go into your function and instead of clicking on the general or testing tab, go to trigger instead.

If you just use your browser to go to the URL you’ll activate your code. If the code runs alright the page will just read “OK”, you can then check your Twitter account and see the results of your function.

We don’t want to have to do that every time but, fortunately, Google has a way to regularly activate a function – Cloud Scheduler. Copy the URL that you found in the trigger tab. Then go to the Cloud Scheduler section.

Click Create Job and then select a region – us-central should be fine.

When you’re setting up your scheduler, the Google documentation is really helpful. This is also a great resource for explaining unix-cron format, which is the format you need to write your timings out in.

You can give it whatever name and description you want as long as it’s descriptive enough for you to remember.

The Frequency field is where you write your unix-cron description of what times to activate. The one you can see here means it’ll activate every 15 minutes.

In the URL field you write the activation URL you copied earlier.

Then just hit CREATE.

To wrap up

So now you have your code running on Google servers. You haven’t had to set up any infrastructure but it’ll run independent of you. It’s doing something quite simple and it’s only activated every fifteen minutes so you should be operating comfortably within the free tier.

This should also give you some idea of how someone might set up some of these simpler bots, like my name change monitor.

Anything I’ve missed? Any cool ideas for bots? Let me know in the comments or tweet me @robinlord8.

Leave a Reply

Your email address will not be published. Required fields are marked *