I subscribe to several block lists on Twitter, as part of my efforts to avoid drama. One of the lists I subscribed to turned out to be much too aggressive, and I suspect that I’m blocking a bunch of people that I probably don’t really want to be blocking.
There are about 9000 people on this particular list, so unblocking them manually is highly impractical, and unsubscribing from the list does not unblock them. So I downloaded this list as a CSV file, and wrote a python script to go through it, automagically unblocking them for me.
A couple of features:
- It unblocks 100 IDs, then pauses for 8 seconds, so as not to run afoul of the Twitter API rate limit.
- The CSV that you get when you export your block list from Twitter, isn’t really a CSV, because there is only one column in the file, and no delimiters of any kind. So rather than import the CSV module and read the file as a CSV, I just have it reading the files like any text file. It works fine.
- I wanted to get an email when it finishes the list, or when it encounters errors, so I pasted in an email function that I use quite a bit in other scripts.
- This does require having a Twitter API key. There are many sites out there with instructions on how to obtain one, so I’m not going to cover that here. I already have several, as I have several Python scripts running a variety of Twitter tasks for me.
- Added in some error handling.
- Added command line arguments so that you specify the list file in the command line, and can optionally specify a line number to start from if the script bombs out partway through. This was happening frequently while I sorted out how to deal with trying to unblock deleted twitter accounts and such. Instead of erroring out, it now simply moves on to the next line. Not so much an issue now, but the capability is still there.
Usage: python3 twitterunblock.py <file.csv> <optional – starting line number>
#!/usr/bin/python3 # Author: DeadTOm - firstname.lastname@example.org # License: GPLv2 - https://www.gnu.org/licenses/gpl-2.0.html # Python Version: 3.6.1 # Description: Unblock a list of twitter IDs from a csv # Usage: python3 twitterunblock.py <file.csv> <optional - starting line number> from twython import Twython, TwythonError import time from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText import smtplib import sys APP_KEY = '' APP_SECRET = '' OAUTH_TOKEN = '' OAUTH_TOKEN_SECRET = '' twitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET) if len(sys.argv) == 2: # Check to see what arguments were passed from the command line listfile = str(sys.argv) # Get CSV file name from command line startingnum = 0 # Set the starting line number to zero, since none was specified elif len(sys.argv) == 3: listfile = str(sys.argv) # Get CSV file name from command line startingnum = int(sys.argv) + 1 # Get the starting line number from the command line. Offset by one, because computers count from zero else: # If nothing was passed from the command line, print usage and exit print('Usage: python3 twitterunblock.py <file.csv> <starting line number>') sys.exit() def unblock(blocklistfile, currentnum): linecount = 0 global linenum # Needed to modify the global variable, outside the function linenum = 0 # Keep track of line numbers when reading files global startingnum # Needed to modify the global variable, outside the function startingnum = int(currentnum) # Set starting num to the number passed to the function with open(blocklistfile) as blocklist: # Open downloaded blocklist file, and iterate through each line for idnum in blocklist: if linenum >= startingnum: # Skip lines we've already read startingnum = linenum # Set the global variable "startingnum" to the current line number, so if the destroy_block command erros out, the function will know where to resume print('Line num: ' + str(linenum) + ' Line count: ' + str(linecount) + ' Unblocking ' + idnum) twitter.destroy_block(user_id=idnum) linecount += 1 # Increment linecount if linecount == 100: # Every 100 lines, pause for eight seconds, then reset the counter time.sleep(8) linecount = 0 else: print('Already unblocked ' + 'Line count: ' + str(linenum) + ' ' + idnum) linenum += 1 # Increment linenum def sendmail(body, subj): # Put together the mailer and send the message to me, using my mail server fromaddr = 'from@emailaddress' toaddr = 'to@emailaddress' msg = MIMEMultipart() msg['Subject'] = subj msg['From'] = fromaddr msg['To'] = toaddr msg.attach(MIMEText(body, 'plain')) server = smtplib.SMTP('mailserver', port) server.ehlo() server.starttls() server.ehlo() server.login('username', 'password') server.sendmail(fromaddr, toaddr.split(','), msg.as_string()) server.quit() try: unblock(listfile, startingnum) body = listfile + ' has been finished.' # Set up the body for the email subj = 'Twitter unblock run finished - ' + listfile # Set up the subject for the email sendmail(body, subj) except TwythonError as oops: if '503' in str(oops): # If a 503 error, wait five minutes and continue print('Encountered \"503\" error. Waiting five minutes, and continuing.') body = 'Error while running ' + listfile + ': ' + str(oops) + ' at line number ' + str(startingnum) + '\n Waiting five minutes and continuing...' # Set up the body for the email subj = 'Twitter unblock run had an error - ' + listfile # Set up the subject for the email sendmail(body, subj) # Email the error message to me time.sleep(600) print('Starting over at line number ' + str(startingnum)) unblock(listfile, startingnum) elif '404' in str(oops): # If a 404 error, move to the next line number, and continue print('This user no longer exists, waiting sixty seconds and then skipping.') body = 'Error while running ' + listfile + ': ' + str(oops) + ' at line number ' + str(startingnum) + '\n Skipping user and continuing...' # Set up the body for the email subj = 'Twitter unblock run had an error - ' + listfile # Set up the subject for the email sendmail(body, subj) # Email the error message to me startingnum += 1 # Increment startingnum, so as to skip the invalid ID number time.sleep(60) print('Starting over at line number ' + str(startingnum)) unblock(listfile, startingnum) else: print(str(oops)) body = 'Error while running ' + listfile + ': ' + str(oops) # Set up the body for the email subj = 'Twitter unblock run had an error - ' + listfile # Set up the subject for the email sendmail(body, subj) # Email the error message to me sys.exit()
You can download the script here.