Created
July 14, 2012 18:58
-
-
Save aperson/3112716 to your computer and use it in GitHub Desktop.
Script to purge bans in a subreddit
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
#!/usr/bin env python3 | |
import json | |
import urllib.request | |
import time | |
import sys | |
import signal | |
from urllib.parse import urlencode | |
import http.cookiejar | |
def sigint_handler(signal, frame): | |
'''Handles ^c''' | |
print('Recieved SIGINT! Exiting...') | |
sys.exit(0) | |
class Reddit(object): | |
"""Base class to perform the tasks of a redditor.""" | |
def __init__(self, username, password): | |
self.username = username | |
self.password = password | |
self.cj = http.cookiejar.CookieJar() | |
self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cj)) | |
self.opener.addheaders = [('User-agent', 'prune_bans.py')] | |
self._login() | |
def _request(self, url, body=None): | |
if body is not None: | |
body = urlencode(body).encode('utf-8') | |
with self.opener.open(url, data=body) as w: | |
time.sleep(2) | |
return json.loads(w.read().decode('utf-8')) | |
def _login(self): | |
print("Logging in as {}.".format(self.username)) | |
body = {'user' :self.username, 'passwd' : self.password, 'api_type' : 'json'} | |
resp = self._request('https://www.reddit.com/api/login', body) | |
self.modhash = resp['json']['data']['modhash'] | |
def post(self, url, body): | |
"""Sends a POST to the url and returns the json as a dict.""" | |
if 'api_type' not in body: body['api_type'] = 'json' | |
body['uh'] = self.modhash | |
return self._request(url, body) | |
def get(self, url): | |
if not url.endswith('.json'): url += '.json' | |
return self._request(url) | |
def process_subreddit(redditor, subreddit, months=None, dry=False): | |
print("Processing the bans in /r/{}.".format(subreddit)) | |
processed = 0 | |
found = 0 | |
r = redditor | |
banned_list = r.get('http://www.reddit.com/r/{}/about/banned/'.format(subreddit)) | |
try: | |
with open('banned_list.json') as f: | |
cache = json.loads(f.read()) | |
except IOError: | |
cache = dict() | |
for i in banned_list['data']['children']: | |
found += 1 | |
if i['name'] not in cache: | |
print('Getting info on: ' + i['name']) | |
try: | |
u = r.get('http://www.reddit.com/user/' + i['name']) | |
# since they're not banned, we'll cache the last activity time | |
data = u['data']['children'] | |
if data: | |
cache[i['name']] = data[0]['data']['created_utc'] | |
else: | |
cache[i['name']] = 0 | |
except urllib.error.HTTPError: | |
# since they are banned, we'll just add that as such | |
cache[i['name']] = 'banned' | |
finally: | |
with open('banned_list.json', 'w') as f: | |
f.write(json.dumps(cache)) | |
if cache[i['name']] == 'banned': | |
print("{} is shadowbanned or deleted, removing from /r/{}'s ban list.".format( | |
i['name'], subreddit)) | |
body = {'executed' : 'removed', 'type' : 'banned', 'r' : subreddit, 'id' : i['id']} | |
if not dry: | |
r.post('http://www.reddit.com/api/unfriend', body) | |
processed +=1 | |
elif months: | |
months_secs = months * 2592000 | |
if cache[i['name']] < (time.time() - months_secs): | |
print("{} is inactive over {} month[s], removing from /r/{}'s ban list.".format( | |
i['name'], months, subreddit)) | |
body = {'executed' : 'removed', 'type' : 'banned', | |
'r' : subreddit, 'id' : i['id']} | |
if not dry: | |
r.post('http://www.reddit.com/api/unfriend', body) | |
processed += 1 | |
print("Found {} bans; processed {}".format(found, processed)) | |
if __name__ == '__main__': | |
signal.signal(signal.SIGINT, sigint_handler) | |
args = sys.argv[1:] | |
if len(args) >= 3: | |
if args[0] in ('-d', '--dry-run'): | |
print("Performing a dry run.") | |
dry_run = True | |
args = args[1:] | |
else: | |
dry_run = False | |
redditor = Reddit(args[0], args[1]) | |
try: | |
months = int(args[2]) | |
for i in args[3:]: | |
process_subreddit(redditor, i, months=months, dry=dry_run) | |
except ValueError: | |
for i in args[2:]: | |
process_subreddit(redditor, i, dry=dry_run) | |
else: | |
print("USAGE:\npython3 prune_bans.py <username> <password> [subreddit,]", | |
"\n-OR-\npython3 prune_bans.py <username> <password> <months> [subreddit,]", | |
"\nMonths can be in any amount as long as it's a number. Subreddits", | |
"\ncan be ran in batches by listing multiples or just singly.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment