Build A Tweet Bot With Python

waleadesina
👁️ 21,325 views
💬 comments

This article demonstrates how to build a tweet bot with Python programming language. Typically, a bot performs tasks that are both simple and repetitive in nature, at a much higher rate than would be possible for a human alone.

The possibilities of what could be achieved on Twitter is endless, and with 500 million+ tweets per day, there’s a lot of data to analyze and to play with. A tweet bot is a program that interacts with Twitter automatically like post tweets follow users, favorite or retweet tweets, or perform any other function possible on Twitter.

Twitter bots can be useful through providing information or updates, and they can also make Twitter more interesting for users.

Table of Contents

    What We'll Build

    There are different classifications of tweet bots depending on the function they perform. This tutorial would work through building a tweet bot that takes any image you tweet at it and randomly rearranges blocks of pixels of the image to create a new scrambled image and replies the tweet with the newly formed image.

    Create Your Own Bot

    Writing a Twitter bot is easy. You can write a Twitter bot in just about any language you please.

    Prerequisites

    In this tutorial we would be using Python programming language so one of the prerequisites includes a Python programming environment, other prerequisites are:

    1. A Twitter account
    2. Tweepy: An easy-to-use Python library for accessing the Twitter API
    3. PIL : Python Imaging Library

    Create A Twitter Account

    The first step is creating a Twitter account https://twitter.com/signup. Once this is done the next step is to create a new application.

    Create a Twitter App

    • Go to apps.twitter.com and click on 'Create New App ' button
    • Fill out the details of the form correctly
    • Read the developer agreement section, and check the box at the bottom if you agree. Then click on the ‘Create your Twitter application’ button

    Keys and Access Tokens

    In order to post to a Twitter account automatically, you have to get access keys for your account.

    1. After creating your new app, you would be redirected to its own page. If you weren’t, go to apps.twitter.com and click on your app's name.
    2. On the app’s page, click on the ‘Keys and Access Tokens’ tab
    3. At the bottom of this page, click on the ‘Create my access token’ button.
    4. Make sure you make note of the following four keys, as you will need these later.

    Coding The Bot

    Twitter provides REST APIs you can use to interact with their service. There is also a bunch of Python-based clients out there that we can use without re-inventing the wheel. In particular, Tweepy in one of the most interesting and straightforward to use, so let’s install it:

    pip install tweepy

    We also need to install PIL, a Python Imaging Library (PIL) that adds image processing capabilities to the Python interpreter. This library supports many file formats and provides powerful image processing and graphics capabilities.You can install PIL with pip:

    pip install Pillow

    Now that we have tweepy and PIL installed, we can begin to lay the structure of the bot application

    tweetbot \
    |-- bot.py
    |-- secrets.py

    Storing Credentials

    The secrets.py file holds valuable information which would be needed to access your Twitter account. Anyone who has access to these strings can use your Twitter account, so you don’t want to share these, or make them public.

     # secrets.py
    
    consumer_key = 'YOUR-CONSUMER-KEY'
    consumer_secret = 'YOUR-CONSUMER-SECRET'
    access_token = 'YOUR-ACCESS-TOKEN'
    access_secret = 'YOUR-ACCESS-SECRET'
    

    Replace the following variables with values from the "Keys and Access Tokens" tab of your Twitter app.

    OAuth Authentication

    Tweepy supports OAuth authentication. Authentication is handled by the tweepy.AuthHandler class. In the bot.py add the following

    # bot.py
    
    import tweepy
    from secrets import *
    
    #create an OAuthHandler instance
    # Twitter requires all requests to use OAuth for authentication
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret) 
    
    auth.set_access_token(access_token, access_secret)
    
     #Construct the API instance
    api = tweepy.API(auth) # create an API object
    

    The api variable is now our entry point for most of the operations we can perform with Twitter. The API class provides access to the entire Twitter RESTful API methods. Each method can accept various parameters and return responses. Please refer to API Reference for more information.

    Some of the many things we can do with the API like read tweets on your timeline

    
    public_tweets = api.home_timeline()
    for tweet in public_tweets:
        print(tweet.text)
    

    Or get the list of all your followers

    
    user = api.get_user('picscrambler')
    for friend in user.friends():
       print(friend.screen_name)
    

    Streaming With Tweepy

    The tweet bot we will build in this tutorial would watch for images that were tweeted at it, and replies with scrambled pixel versions of the original image. To do these we would need a way to keep the connection open to being able to respond to all incoming and upcoming tweets, this is where the streaming API comes in. Tweepy makes it easier to use the Twitter streaming API by handling authentication, connection, creating and destroying the session, reading incoming messages, and partially routing messages.

    The streaming API is quite different from the REST API because the REST API is used to pull data from Twitter but the streaming API pushes messages to a persistent session. This allows the streaming API to download more data in real time than could be done using the REST API. To read more about the Streaming API See the Twitter Streaming API Documentation.

    Inside bot.py

    #bot.py
    
    import tweepy
    
    #create a class inherithing from the tweepy  StreamListener
    class BotStreamer(tweepy.StreamListener):
    
        # Called when a new status arrives which is passed down from the on_data method of the StreamListener
        def on_status(self, status):
            username = status.user.screen_name 
            status_id = status.id
    
        #entities provide structured data from Tweets including resolved URLs, media, hashtags and mentions without having to parse the text to extract that information
            if 'media' in status.entities:
                for image in status.entities['media']:
                    tweet_image(image['media_url'], username, status_id)
    

    Using the streaming API has three steps:

    • Create a class inheriting from StreamListener
    • Using that class create a Stream object
    • Connect to the Twitter API using the Stream

    We just created a class that inherits from StreamListener class overriding the on_status method capturing the username of the account that posted the tweet and tweet id and checking if an image exists in the status object (tweet) and passes it all to the tweet_image function which we are yet to write.

    Next, we create a stream object

    # bots.py
    
    myStreamListener = BotStreamer()
    
     #Construct the Stream instance
    stream = tweepy.Stream(auth, myStreamListener)

    A number of Twitter streams are available through Tweepy. Most cases will use the filter, the user_stream, or the sitestream method. For more information on the capabilities and limitations of the different streams, see Twitter Streaming API Documentation.

    In this example, we will use a filter to stream all tweets tweeted at our bot . The track parameter is an array of search terms to watch for.

    stream.filter(track=['@picscrambler'])

    In this case, the track parameter should be the name of your Twitter application.

    Scramble Image Pixel

    Now let's code up our tweet_image function

    # bots.py
    
    import requests
    from io import BytesIO
    from PIL import Image
    
    def tweet_image(url, username, status_id):
    
        filename = 'temp.png'
        # send a get request
        request = requests.get(url, stream=True)
        if request.status_code == 200:
            # read data from downloaded bytes and returns a PIL.Image.Image object
            i = Image.open(BytesIO(request.content))
            # Saves the image under the given filename
            i.save(filename)
            scramble(filename)
            # Update the authenticated user’s status
            api.update_with_media('scramble.png', status='@{0}'.format(username), in_reply_to_status_id=status_id)
        else:
            print("unable to download image")

    We use the Python request http library to download the image from the url and write its content into a temp.png file using the Python image library then call a scramble function on the PIL image object to produce a scrambled pixel image which is then used to reply the original tweet using the API object.

    We are yet to write our image scrambler function

    # bots.py
    
    import random
    
    def scramble(filename):
        BLOCKLEN = 64  # Adjust and be careful here.
    
        img = Image.open(filename)
        width, height = img.size
    
        xblock = width // BLOCKLEN
        yblock = height // BLOCKLEN
        # creates sequence of 4-tuples (box) defining the left, upper, right, and lower pixel coordinate
        blockmap = [(xb * BLOCKLEN, yb * BLOCKLEN, (xb + 1) * BLOCKLEN, (yb + 1) * BLOCKLEN)
                    for xb in range(xblock) for yb in range(yblock)]
    
        shuffle = list(blockmap)
    
        #shuffle the sequence
        random.shuffle(shuffle)
    
        # Creates a new image with the given mode and size.
        result = Image.new(img.mode, (width, height))
        for box, sbox in zip(blockmap, shuffle):
            # Returns a rectangular region from this original image.
            crop = img.crop(sbox)
            # Pastes the cropped pixel into the new image Object
            result.paste(crop, box)
        result.save('scramble.png')

    At this point, the bots.py should look like this

    # bots.py
    
    import random
    from io import BytesIO
    
    import requests
    import tweepy
    from PIL import Image
    from PIL import ImageFile
    
    from secrets import *
    
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    
    auth = OAuthHandler(consumer_key, consumer_secret) # Twitter requires all requests to use OAuth for authentication
    auth.set_access_token(access_token, access_secret) 
    api = tweepy.API(auth)
    
    def tweet_image(url, username, status_id):
        filename = 'temp.png'
        # send a get request
        request = requests.get(url, stream=True)
        if request.status_code == 200:
            # read data from downloaded bytes and returns a PIL.Image.Image object
            i = Image.open(BytesIO(request.content))
            # Saves the image under the given filename
            i.save(filename)
            scramble(filename)
            # Update the authenticated user’s status
            api.update_with_media('scramble.png', status='@{0}'.format(username), in_reply_to_status_id=status_id)
        else:
            print("unable to download image")
    
    def scramble(filename):
        BLOCKLEN = 64  # Adjust and be careful here.
    
        img = Image.open(filename)
        width, height = img.size
    
        xblock = width // BLOCKLEN
        yblock = height // BLOCKLEN
        # creates sequence of 4-tuples (box) defining the left, upper, right, and lower pixel coordinate
        blockmap = [(xb * BLOCKLEN, yb * BLOCKLEN, (xb + 1) * BLOCKLEN, (yb + 1) * BLOCKLEN)
                    for xb in range(xblock) for yb in range(yblock)]
    
        shuffle = list(blockmap)
    
        # shuffle the sequence
        random.shuffle(shuffle)
    
        # Creates a new image with the given mode and size.
        result = Image.new(img.mode, (width, height))
        for box, sbox in zip(blockmap, shuffle):
            # Returns a rectangular region from this original image.
            crop = img.crop(sbox)
            # Pastes the cropped pixel into the new image Object
            result.paste(crop, box)
        result.save('scramble.png')
    
    # create a class inheriting from the tweepy  StreamListener
    class BotStreamer(tweepy.StreamListener):
        # Called when a new status arrives which is passed down from the on_data method of the StreamListener
        def on_status(self, status):
            username = status.user.screen_name
            status_id = status.id
    
            # entities provide structured data from Tweets including resolved URLs, media, hashtags and mentions without having to parse the text to extract that information
            if 'media' in status.entities:
                for image in status.entities['media']:
                    tweet_image(image['media_url'], username, status_id)
    
    myStreamListener = BotStreamer()
    # Construct the Stream instance
    stream = tweepy.Stream(auth, myStreamListener)
    stream.filter(track=['@picscrambler'])

    That's all we need to test this bot. Run bots.py from terminal and post a tweet with an image @picscrambler. After a few seconds the bot replies with a scrambled version of the original picture. You can see a minimal working example of the Twitter bot in this githhub repository tweetbot

    Conclusion

    This tutorial walked through setting up and running a Twitter bot to automatically interact with the Twitter social media platform. There is a lot more that you can do with the Twitter API and with libraries like Tweepy that make it easy for developers to make use of Twitter.

    REFERENCES