Skip to content

Instantly share code, notes, and snippets.

@gavin19
Last active May 19, 2020 16:12
Show Gist options
  • Save gavin19/7972e5554def6bd4edc62bed29a92107 to your computer and use it in GitHub Desktop.
Save gavin19/7972e5554def6bd4edc62bed29a92107 to your computer and use it in GitHub Desktop.
"""Python subreddit utils."""
import os
import sys
import argparse
import shutil
from configparser import ConfigParser
from time import sleep
from urllib.request import (Request, urlopen, urlretrieve)
from zipfile import ZipFile
import praw
import prawcore
class SrUtils:
"""Main class."""
def __init__(self):
"""Init."""
self.path = sys.path[0]
self.reddit = None
self.login()
def login(self):
"""Log in via script app."""
conf = ConfigParser()
if os.path.exists('creds.ini'):
conf.read('creds.ini', encoding='utf-8')
else:
raise FileNotFoundError('Config file, creds.ini, was not found.')
user = conf.get('creds', 'username')
pwd = conf.get('creds', 'password')
app_id = conf.get('creds', 'app_id')
app_secret = conf.get('creds', 'app_secret')
user_agent = conf.get('creds', 'user_agent')
self.reddit = praw.Reddit(client_id=app_id,
client_secret=app_secret,
username=user,
password=pwd,
user_agent=user_agent)
self.parse_args()
def parse_args(self):
"""Parse the arguments."""
parser = argparse.ArgumentParser()
parser.add_argument('--backup', '-b', nargs="*")
parser.add_argument('--dupe', '-d', nargs=2)
parser.add_argument('--restore', '-r', nargs=2)
args = parser.parse_args()
if args.backup:
self.backup(args.backup)
elif args.dupe:
self.dupe(args.dupe)
elif args.restore:
self.restore(args.restore)
else:
print("No option selected")
def backup(self, loc):
"""Backup the given sub to a zip."""
source = loc[0]
if not os.path.exists('backups'):
os.makedirs('backups')
if len(loc) < 2:
archive_name = source + '.zip'
else:
archive_name = loc[1]
backup_path = os.path.join(self.path, 'backups')
if archive_name in os.listdir(backup_path):
print(archive_name + ' already exists.')
print('If you proceed it will be replaced with a current backup')
while True:
inp = input("Proceed - y/n: ")
if inp not in "YyNn":
print("y to proceed or n to exit")
else:
break
if inp.lower() == 'n':
print('Exiting...')
sleep(2)
sys.exit()
else:
os.remove(os.path.join(backup_path, archive_name))
temp_path = source + '_tmp'
if os.path.exists(temp_path):
shutil.rmtree(temp_path)
os.makedirs(temp_path)
os.chdir(temp_path)
archive = {}
sub = self.reddit.subreddit(source)
archive['settings'] = self.get_subreddit_settings()
archive['user_flair'] = self.get_user_flair_templates()
archive['link_flair'] = self.get_link_flair_templates(sub)
stylesheet = self.get_subreddit_stylesheet()
archive['css'] = stylesheet.stylesheet
images = stylesheet.images
if images:
archive['imgs'] = self.get_images(images)
with open('backup.txt', 'w', encoding='utf-8') as f:
f.write(str(archive))
items = os.listdir()
with ZipFile(archive_name, 'w') as zip:
for item in items:
zip.write(item)
src = os.path.abspath(archive_name)
target = os.path.join(backup_path, archive_name)
shutil.move(src, target)
os.chdir(self.path)
shutil.rmtree(temp_path)
print('Backup completed...')
@staticmethod
def get_subreddit_settings(sub):
"""Fetch the subreddit settings."""
settings = sub.mod.settings()
return settings
@staticmethod
def get_user_flair_templates(sub):
"""Fetch user flair templates."""
user_flair = [t for t in sub.flair.templates]
return user_flair
@staticmethod
def get_subreddit_stylesheet(sub):
"""Fetch the subreddit settings."""
stylesheet = sub.stylesheet()
return stylesheet
@staticmethod
def get_link_flair_templates(sub):
"""Get templates from existing/test submission."""
templates = []
id = [s.id for s in sub.hot(limit=1)]
if not id:
print("""
No posts were found in the target subreddit.
At least one post must exist in the subreddit to fetch
the link flair templates.
If you don't want to backup the templates then you can
skip this part,
otherwise a test post will be made, the templates fetched,
and the post deleted.
""")
while True:
skip = input("Skip this part - y/n: ")
if skip not in "YyNn":
print("y to skip, n to backup")
else:
break
if skip.lower() == 'n':
templates = self.make_test_post(sub.display_name)
else:
templates = self.make_test_post(sub.display_name)
return templates
@staticmethod
def get_images(imgs):
"""Download subreddit stylesheet images."""
count = 1
total = len(imgs)
for i in imgs:
url = i['url']
ext = '.' + url.split('.')[-1]
name = i['name'] + ext
urlretrieve(url, name)
print(str(count) + ' of ' + str(total) + ' - ' + name)
count += 1
sleep(1)
@staticmethod
def make_test_post(sub):
"""Create/delete test post to fetch link flair templates."""
post = sub.submit('Link flair test', url='https://reddit.com/#test')
templates = post.flair.choices()
post.delete()
return templates
SrUtils()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment