-
-
Save adacable/c22716752251965e76f30ac19fbbd54b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#usage: | |
helpText = """ | |
Tweet deletion script based on a downloaded archive from the first ones you tweeted to the latest, using the old, less rate limited API, allowing you to get everything ever as fast as possible(~10k tweets, likes or messages an hour). | |
python tweet_deleter.py [-t] [-m] [-l] [filename] | |
Filename is the location of the unzipped twitter archive, terminated in a / | |
If no filename is specified, will use the one hardcoded in the script. | |
-t will delete tweets | |
-l will delete likes | |
-m will delete direct messages you've sent | |
Fancy argument parsing is not implimented you can't do -tlm or similar, you can't the folder name needs to be the last option. | |
API keys and archive folder can be hardcoaded. | |
Twitter won't let you unretweet tweets from accounts you don't have access to- Expect a few "Sorry, you are not authorized to see this status" errors at the bottom/as you go through. | |
Tweets that aren't deleted are shown twice: once as an error message as you progress through, and once at the bottom in a summary of all errors. In some cases there may be many errors(like if you ran it partway and then stopped) | |
You may want to use twitter archive parser first, to save full resolution versions of all of your images before you delete them. | |
https://github.com/timhutton/twitter-archive-parser" | |
""" | |
#EDIT THIS | |
archive_folder = "" #absolute path to the folder where you unzipped the archive twitter sent you(terminated in a /). If blank, reads the last argument from the comand. | |
consumer_key = "JRqBpgYCsNmuorouNhZLRS9Xx"#twitter api keys- use your own if you have them! | |
consumer_secret = "YHk7faSxq0kNJC1bxPSRIxYPP6JBibO0WrTXyRdH8XU1silijo" | |
access_token = "" #if left blank the script will authorise you and print them for you to use next time. | |
access_secret = "" | |
#api version to use. only 1.1 is currently supported, so this is entirley decorative and probably always willl be because I have 1.1 credentials, am willing to share them with my friends and v2.0 sucks for deleting things. | |
apiversion = "1.1" | |
# ignore below here | |
try: | |
import tweepy | |
except: | |
print("You need to install tweepy to run this. Run 'pip install tweepy' to install tweepy") | |
exit() | |
import sys | |
import glob | |
import json | |
def main(): | |
auth() | |
global archive_folder | |
if archive_folder == "": | |
archive_folder = sys.argv[-1] | |
if len(glob.glob(archive_folder)) != 1: | |
print("Seems like your archive file isn't in the right place. Make sure the location is absolute, and terminated in a /") | |
exit() | |
if "-t" in sys.argv: | |
deleteItems("tweets") | |
elif "-l" in sys.argv: | |
deleteItems("likes") | |
elif "-m" in sys.argv: | |
deleteItems("messages") | |
else: | |
print("please add a -t, -m or -l to delete something") | |
print(helpText) | |
exit() | |
announceErrors() | |
def progressInit(toCount, deleteType): | |
global noOfTweets | |
global noOfTweetsDeleted | |
global errors | |
noOfTweets = len(toCount) | |
noOfTweetsDeleted = 0 | |
errors = [] | |
print("%s %s to delete"%(noOfTweets,deleteType)) | |
print("Starting to actually delete %s"%deleteType) | |
def announceErrors(): | |
for printError in errors: | |
print(printError['id']) | |
print(printError['error']) | |
def auth(): | |
if apiversion == "1.1": | |
if (access_token == "") & (access_secret == ""): | |
v11auth() | |
global api | |
tweepyAuth = tweepy.OAuthHandler(consumer_key, consumer_secret) | |
tweepyAuth.set_access_token(access_token, access_secret) | |
api = tweepy.API(tweepyAuth) | |
def deleteFailed(errorIn, tweetID,failiureType): | |
global noOfTweetsDeleted | |
print("%s/%s failed to delete %s %s: %s"%(noOfTweetsDeleted,noOfTweets,failiureType[:-1],tweetID,errorIn)) | |
errors.append({'id':tweetID, 'error':errorIn}) | |
noOfTweetsDeleted = noOfTweetsDeleted + 1 | |
def progress(idprint,deleteType): | |
global noOfTweetsDeleted | |
noOfTweetsDeleted = noOfTweetsDeleted + 1 | |
return "%s/%s deleted %s:, ID %s"%(noOfTweetsDeleted,noOfTweets, deleteType[:-1],idprint) | |
def deleteItems(deleteType): | |
print("Begining work on deleting %s"%deleteType) | |
toDelete = extract_ids(deleteType) | |
progressInit(toDelete,deleteType) | |
for tid in toDelete: | |
try: | |
deleteitem(tid,deleteType) | |
print(progress(tid,deleteType)) | |
except Exception as errorOut: | |
deleteFailed(errorOut,tid,deleteType) | |
def extract_ids(deleteType): | |
print("getting a list of all %s ids from your archive"%(deleteType[:-1])) | |
if deleteType == "tweets": | |
fileLocation = archive_folder + "/data/tweets.js" | |
if deleteType == "likes": | |
fileLocation = archive_folder + "/data/like.js" | |
if deleteType == "messages": | |
fileLocation = archive_folder + "/data/direct-messages.js" | |
idsList = [] | |
archive_file = open(fileLocation) | |
JsonObjects = json.loads("["+"\n".join(archive_file.readlines()[1:])) | |
if deleteType == "messages": | |
dmConversations = [i['dmConversation'] for i in JsonObjects] | |
userID = api.verify_credentials().id_str | |
for dmConversation in dmConversations: | |
for message in dmConversation["messages"]: | |
try: | |
if message["messageCreate"]["senderId"] == userID: | |
idsList.append(message["messageCreate"]["id"]) | |
except: | |
pass | |
elif deleteType == "tweets": | |
idsList = [i['tweet']['id'] for i in JsonObjects] | |
elif deleteType == "likes": | |
idsList = [i['like']['tweetId'] for i in JsonObjects] | |
return idsList | |
def deleteitem(ID,deleteType): | |
if deleteType == "tweets": | |
api.destroy_status(ID) | |
if deleteType == "likes": | |
api.destroy_favorite(ID) | |
if deleteType == "messages": | |
api.delete_direct_message(ID) | |
def v11auth(): | |
auth = tweepy.OAuthHandler(consumer_key, consumer_secret,callback="oob") | |
auth_url = auth.get_authorization_url() | |
try: | |
import webbrowser | |
webbrowser.open(auth_url) | |
print("Please log in to twitter in your web browser, and paste the pin below") | |
except: | |
print('Please open this url and log in: ' + auth_url) | |
verifier = input('PIN: ').strip() | |
global access_token | |
global access_secret | |
access_token,access_secret = auth.get_access_token(verifier) | |
print("Access token: "+ access_token) | |
print("Access secret: "+ access_secret) | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment