'''Purge bogus followers from your account.'''
import ConfigParser
import os
import sys
import twitter
from time import sleep
import json
import time
class TweetRc(object):
def __init__(self):
self._config = None
def GetConsumerKey(self):
return self._GetOption('consumer_key')
def GetConsumerSecret(self):
return self._GetOption('consumer_secret')
def GetAccessKey(self):
return self._GetOption('access_key')
def GetAccessSecret(self):
return self._GetOption('access_secret')
def _GetOption(self, option):
try:
return self._GetConfig().get('Tweet', option)
except:
return None
def _GetConfig(self):
if not self._config:
self._config = ConfigParser.ConfigParser()
self._config.read(os.path.expanduser('~/.tweetrc'))
return self._config
def report_spam(api, user):
url = "%s/blocks/create.json" % api.base_url
json = api._RequestUrl(url, 'POST', data={'user_id': user.id, 'skip_status': 1})
data = api._ParseAndCheckTwitter(json.content)
def over_limit(rate):
return rate['remaining'] <= 0 and rate['reset'] - time.time() > 0
def rate_wait(rate):
while over_limit(rate):
print "WAITING on ", rate, "for", rate['reset'] - time.time()
sleep(rate['reset'] - time.time())
def rate_limit(api, last_rate):
# make sure we're not over on rate limiting
rating = last_rate['resources']['application']['/application/rate_limit_status']
if over_limit(rating):
print "Rating limit limited..."
rate_wait(rating)
rating = api.GetRateLimitStatus()
user_limit = rating['resources']['users']['/users/lookup']
print "User limits", user_limit
if over_limit(user_limit):
print "User lookup limited...."
rate_wait(user_limit)
return rating
def main():
rc = TweetRc()
once = len(sys.argv) > 1
consumer_key = rc.GetConsumerKey()
consumer_secret = rc.GetConsumerSecret()
access_key = rc.GetAccessKey()
access_secret = rc.GetAccessSecret()
if not consumer_key or not consumer_secret or not access_key or not access_secret:
print "You must edit ~/.tweetrc accordingly."
api = twitter.Api(consumer_key=consumer_key, consumer_secret=consumer_secret,
access_token_key=access_key,
access_token_secret=access_secret)
cursor = -1
last_rate = api.GetRateLimitStatus()
count = 0
if os.path.exists("followers.json"):
followers = json.load(open("followers.json"))
else:
followers = api.GetFollowerIDs(cursor=cursor)
with open("followers.json",'w') as followers_store:
followers_store.write(json.dumps(followers))
print "SAVED", len(followers), "TO followers.json"
# skip the ones already processed
users = []
for user_id in followers:
if os.path.exists("blocked/%s.json" % user_id) or os.path.exists("skipped/%s.json" % user_id):
print "Processed", user_id, "Already"
else:
users.append(user_id)
print "Processing %d users" % len(users)
while users:
try:
id_list = []
if len(users) >= 100:
for i in range(0, 100):
id_list.append(users.pop(0))
else:
id_list = users
users = []
batch = api.UsersLookup(user_id = id_list)
while batch:
user = batch.pop(0)
if os.path.exists("blocked/%s.json" % user.id) or os.path.exists("skipped/%s.json" % user.id):
print "Already did", user.id
continue
print user.screen_name, user.id, user.followers_count, user.statuses_count, user.friends_count,
if user.friends_count < 10 or user.statuses_count < 10 or user.followers_count < 10:
data_file = "blocked/%s.json" % user.id
with open(data_file, "w") as out:
out.write(json.dumps(user.AsJsonString()))
report_spam(api, user)
count += 1
print "BLOCKED!"
else:
data_file = "skipped/%s.json" % user.id
with open(data_file, "w") as out:
out.write(json.dumps(user.AsJsonString()))
print "SKIPPED!"
except twitter.TwitterError, e:
print "Rate limited.", e
print "Waiting for rate limit to pass.", len(users), "Remaining"
last_rate = rate_limit(api, last_rate)
print "BLOCKED", count
if __name__ == "__main__":
main()