Skip to content

Instantly share code, notes, and snippets.

@adacable
Created November 15, 2022 17:39
Show Gist options
  • Save adacable/c22716752251965e76f30ac19fbbd54b to your computer and use it in GitHub Desktop.
Save adacable/c22716752251965e76f30ac19fbbd54b to your computer and use it in GitHub Desktop.
#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