Automate Twitter Following with PowerShell

Published:17 December 2019 - 7 min. read

Are you on Twitter? If not, you’re missing out. Twitter is the best social media platform to keep up with the fast pace of tech. But there are millions of people on Twitter. How do you track down interesting people? In this article, I’ll show you how to do just at and automate it!

There are many different ways to discover interesting people on Twitter. You’ll find dozens of different tools and services that help you but they’re not perfect. Some are paid services, some are broken and some don’t have the features you’re looking for.

Instead of using some fancy service, did you know you can create your own tool? If you have a little bit of PowerShell knowledge, you can easily query Twitter’s API yourself and discover all the Twitter users you’d like. But how?

Since you can discover interesting Twitter users to follow many different ways, this article is going to attempt to solve this problem in three steps:

  1. Finding all followers of popular Twitter accounts that you would consider “interesting”. What people do you already follow with a lot of followers that you feel would be tweeting the same, general type of content?
  2. Filtering potential followers by attributes such as words in their profile, not having a default profile image, do not have a protected Twitter account, etc.
  3. Following all found screen names.

The best part of all, this will all be done via a script so it’s 100% automatable and can be run again at any time you wish.

Prerequisites

This automate Twitter following project is going to be a hands-on demonstration. You’ll be building your own script to query Twitter and manage your Twitter friends. If you plan on following along, please be sure you have the following in place:

  • A Twitter account
  • A Twitter application. You will find the steps on how to do this on the MyTwitter blog post. This is required to gather some API keys and access tokens to authenticate to your account.
  • Windows PowerShell or PowerShell 6+. The examples in this article were run on PowerShell v6.2 on a Mac.
  • An intermediate understanding of PowerShell
  • A list of Twitter screen names that have the type of followers you’d like to follow. This article will “seed” an initial list of people using the followers of another Twitter account.

Getting the Automate Twitter Following Script Set Up

To perform the heavy lifting such as authentication and making the API calls, you’re going to first depend on Marc Kellerman’s PSTwitterAPI PowerShell module. This is a handy module that wraps PowerShell around the various Twitter API functions.

Installing the PSTwitterAPI Module

Go ahead and download and install this module from the PowerShell Gallery like below.

PS62> Install-Module -Name PSTwitterAPI

Finding API Keys and Tokens

Once installed, you’ll then need to provide four important pieces of information your Twitter application provides you:

  • API Key
  • API Secret
  • Access Token
  • Access Token Secret

You can find these critical attributes in the Keys and tokens section under your Twitter application as shown below.

Creating a Twitter application
Creating a Twitter application

Passing OAuth Keys and Tokens to PSTwitterAPI

Once you have access to each four of these items, it’s now time to pass them to the PSTwitterAPI module using the Set-TwitterOAuthSettings cmdlet. To do this, call the cmdlet passing each value to the appropriate parameter as shown below.

$OAuthSettings = @{
     ApiKey            = 'xxxxxx'
     ApiSecret         = 'xxxxxx'
     AccessToken       = 'xxxxxx'
     AccessTokenSecret = 'xxxxxx'
}
Set-TwitterOAuthSettings @OAuthSettings

Building Utility Functions

When querying an API, you’ll undoubtedly come across rate limits when trying to automate following Twitter users. There are only a certain number of requests you can perform in a given amount of time. You can read more information about Twitter API rate limits here.

To make managing those times when a query is rate-limited, I’ve created two functions called Get-FriendlyApiErrorResponse and Test-ApiRateLimitResponse. These two PowerShell functions don’t do a whole lot (on purpose) but do one thing well. They prevent the user from not having to worry about specific errors thrown or decisions to make.

function Get-FriendlyApiErrorResponse {
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [System.Management.Automation.ErrorRecord]$ErrorResponse
    )
    if ($ErrorResponse.Exception.Message -match 'You are unable to follow more people at this time') {
        $ErrorResponse.Exception.Message
    } else {
        ($ErrorResponse.ErrorDetails.Message | ConvertFrom-Json).errors.message
    }
}

function Test-ApiRateLimitResponse {
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$ErrorResponse
    )

    $ErrorResponse -match '(Too many requests)|(Rate limit exceeded)'
}

Also, since there will be times when you are rate-limited, it’s handy to know when the script will attempt to run again. Below you will see the Show-Countdown function that does just that.

function Show-Countdown {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [int]$MaxWaitMin
    )

    $timer =  [system.diagnostics.stopwatch]::StartNew()
    do {
        $totalMinsWaited =  [math]::Round($timer.Elapsed.TotalMinutes, 0)
        Write-Host "$($MaxWaitMin - $totalMinsWaited)..." -NoNewline
        Start-Sleep -Seconds 60
    } while ($timer.Elapsed.TotalMinutes -lt $MaxWaitMin)

    $timer.Stop()
}

Populating “Seed” Twitter Friends

Rather than scour the entire Twitterverse, first start with a “seed” list of potential Twitter friends. One way to do that is to first manually define one or more Twitter users with kindred spirits.

  • What type of people do you enjoy following on Twitter?
  • What type of people may have followers that could potentially tweet interesting stuff?

Create a list of these people in a PowerShell array. You’re going to be querying each of their followers.

It’s advisable not to add dozens or hundreds of Twitter screen names in this list. Besides creating an overwhelming timeline, you’re going to be hitting Twitter’s API limit a ton!

$interestingUsers = @('user1','user2','user3')

Defining Interesting Keywords

Next, to filter potential Twitter friends down, even more, define a list of words you’d like to show up in their profiles. Try to come up with some general words they may put in their profile as part of their interests or bio.

Below you’ll find some of my keywords.

$profileDescKeywords = @('sccm', 'powershell', 'engineer', 'azure', 'cloud', 'devops')

Querying Twitter Followers

At this point, it’s time to query each “interesting” user for all of their followers. Since you may potentially have more than one user to query followers for, create a loop as shown below.

$followers = @()
foreach ($user in $interestingUsers) {

}

Inside of that foreach loop, you’ll then need to place a do/while loop. This is necessary due to how the Twitter API responds. Unfortunately, if the account has more than 200 followers, you will have to poll the API more than once. This do/while loop manages this for you.

Inside of that do/while loop, use the Get-TwitterFollowers_List function. This function will poll Twitter’s API and pull down 200 or less of their followers.

You can see below an example of how to implement this logic with comments where necessary. This code brings together the functions built earlier to show you how they can be used.

do {
    try {
        $getFollowParams = @{
            ErrorAction = 'Stop'
            count       = 200
        }
        $getFollowParams.screen_name = $user
        if (Get-Variable -Name 'response' -ErrorAction 'Ignore') {
            $getFollowParams.cursor = $response.next_cursor
        }
        if ($response = Get-TwitterFollowers_List @getFollowParams) {
            Write-Verbose -Message "Get-TwitterFollowers: Retrieved $($response.users.Count) followers from user $ScreenName..."
            $response.users
            
        }
    } catch {
        $errResponse = Get-FriendlyApiErrorResponse -ErrorResponse $_
        if (Test-ApiRateLimitResponse -ErrorResponse $errResponse) {
            Write-Warning "Hit API rate limit. Waiting $RetryInterval minutes..."
            Show-Countdown -MaxWaitMin $RetryInterval
        } else {
            throw $errResponse
        }
    }
} while ($response.next_cursor)

I’ve wrapped all of this code into a function called Get-TwitterFollowers below. This is the first function in your automate Twiter following module!

function Get-TwitterFollowers {
    [CmdletBinding()]
    param
    (
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$ScreenName,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [int]$RetryInterval = 15
    )

    do {
        try {
            $getFollowParams = @{
                ErrorAction = 'Stop'
                count       = 200
            }
            if ($PSBoundParameters.ContainsKey('ScreenName')) {
                $getFollowParams.screen_name = $ScreenName
            }
            if (Get-Variable -Name 'response' -ErrorAction 'Ignore') {
                $getFollowParams.cursor = $response.next_cursor
            }
            if ($response = Get-TwitterFollowers_List @getFollowParams) {
                Write-Verbose -Message "Get-TwitterFollowers: Retrieved $($response.users.Count) followers from user $ScreenName..."
                $response.users
                
            }
        } catch {
            $errResponse = Get-FriendlyApiErrorResponse -ErrorResponse $_
            if (Test-ApiRateLimitResponse -ErrorResponse $errResponse) {
                Write-Host "Hit API rate limit. Waiting $RetryInterval minutes..."
                Show-Countdown -MaxWaitMin $RetryInterval
            } else {
                throw $errResponse
            }
        }
    } while ($response.next_cursor)
}

Automate Following Twitter Accounts

A final task you’ll need to perform is to follow an account. To make the process as easy as possible to account for the API rate-limiting, you can see an example of a function to do this.

This function called Follow-TwitterUser, will reach out to Twitter and attempt to follow an account. If the request is rate-limited, it will back off for a specific period of time and try again up to $MaxRetries.

function Follow-TwitterUser {
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$ScreenName,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [int]$RetryInterval = 15, ## minutes

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [int]$MaxRetries = 5
    )

    $retriesPerformed = 0
    $success = $false
    do {
        try {
            $followParams = @{
                ErrorAction = 'Stop'
                screen_name = $ScreenName
            }
            Write-Verbose -Message "Attempting to follow screen name $ScreenName..."
            $response = Send-TwitterFriendships_Create @followParams
            Write-Verbose -Message 'Successfully followed user.'
            $success = $true
        } catch {
            $errResponse = Get-FriendlyApiErrorResponse -ErrorResponse $_
            if (Test-ApiRateLimitResponse -ErrorResponse $errResponse) {
                $retriesPerformed++
                if ($retriesPerformed -le $MaxRetries) {
                    Write-Warning "Hit API rate limit. Waiting $RetryInterval minutes..."
                    Show-Countdown -MaxWaitMin $RetryInterval
                } else {
                    throw $errResponse
                }
            } else {
                throw $errResponse
            }
        }
    } while (-not $success)
}

Filtering Users Based on Profile Keywords

There will probably be a lot of “junk” and spammy Twitter accounts following your seed accounts. To ensure you don’t follow these accounts, add another layer of filtering.

There are many different criteria you can use to filter out these accounts. In this article, you will see six different items. For me to follow an account, the account must meet these requirements:

  1. Must be following a “seed” Twitter account
  2. Is not protected meaning you have to get permission to follow it
  3. I am not following them
  4. Has a profile defined
  5. Has at least one interesting keyword in their profile. Remember the array you defined earlier called $profileDescKeywords. This is where it will come in handy.
  6. Does not have a default profile image

Following Twitter Users

The Get-TwitterFollowers functions return all followers of a specified account but it doesn’t apply any filters defined above. Below you’ll see an example of some of the filtering done.

You’ll also notice the Follow-TwitterUser function defined above. This code attempts to find an account’s followers based on the filtering criteria and follow each user.

Get-TwitterFollowers -ScreenName $user -Verbose:$VerbosePreference | where {
    $desc = $_.description;
    -not $_.protected -and ## is not a protected account
    -not $_.following -and ## I am not following them already
    -not $_.followed_by -and ## They are not following me
    $_.description -and ## They have a profile
    $_.profile_image_url -notmatch 'default_profile_images' -and ## They don't have a default profilate image
    ($profileDescKeywords | ? { $desc -match $_ }) -and ## They have at least one interesting word in their profile
    $_.screen_name -notin $NeverFollow
} | foreach {
    Follow-TwitterUser -ScreenName $_.screen_name -Verbose:$VerbosePreference
}

If you’d like to download and modify the script created for this project, you may do so via Github.

Before anyone cries about this code and it’s efficiencies, I’ll be the first to tell you this was just a fun project. It is, by no means, a representation of what I’d call “professional” code but did the job for my purposes.

Challenge

In this article, you learned the nuts and bolts of building your own Twitter discovery tool. How could you make it better? From the code you’ve seen here, an awesome PowerShell module could be built! Why not build one, make this code better and share it on GitHub and the PowerShell Gallery?

Hate ads? Want to support the writer? Get many of our tutorials packaged as an ATA Guidebook.

Explore ATA Guidebooks

Looks like you're offline!