Created
February 9, 2020 08:03
-
-
Save Hashbrown777/bb1d4dd2b8a1c41af12054998b1813bf to your computer and use it in GitHub Desktop.
downloads and sets the desktop background to today's top hot image from the specified subreddits
This file contains hidden or 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 python | |
# -*- coding: utf-8 -*- | |
from __future__ import unicode_literals | |
import argparse | |
import ctypes | |
import os | |
#requires version 3.5 of praw | |
import praw | |
import platform | |
import re | |
import requests | |
import sys | |
import time | |
import random | |
import re | |
import glob | |
from configparser import ConfigParser | |
from io import StringIO | |
from collections import defaultdict | |
#from IPython import embed | |
#embed() | |
if sys.version_info <= (2, 6): | |
import commands as subprocess | |
else: | |
import subprocess | |
headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'} | |
def load_config(): | |
default = defaultdict(str) | |
default["nsfw"] = "False" | |
default["time"] = "day" | |
default["display"] = "0" | |
default["output"] = os.path.abspath(os.path.dirname(sys.argv[0])) | |
subs = default["output"] + "/subs."; | |
subnum = int(glob.glob(subs + "*")[0].split(".")[1]) | |
default["subreddit"] = [line.rstrip('\n') for line in open(subs + str(subnum), "r")] | |
newsubnum = str((subnum + 1) % len(default["subreddit"])) | |
os.rename(subs + str(subnum), subs + newsubnum) | |
default["subreddit"] = default["subreddit"][subnum] | |
print(default["subreddit"]) | |
config_path = os.path.expanduser("~/.config/change_wallpaper_reddit.rc") | |
section_name = "root" | |
try: | |
config = ConfigParser(default) | |
with open(config_path, "r") as stream: | |
stream = StringIO("[{section_name}]\n{stream_read}".format(section_name=section_name, | |
stream_read=stream.read())) | |
if sys.version_info >= (3, 0): | |
config.read_file(stream) | |
else: | |
config.readfp(stream) | |
ret = {} | |
# Add a value to ret, printing an error message if there is an error | |
def add_to_ret(fun, name): | |
try: | |
ret[name] = fun(section_name, name) | |
except ValueError as e: | |
err_str = "Error in config file. Variable '{}': {}. The default '{}' will be used." | |
# print sys.stderr >> err_str.format(name, str(e), default[name]) | |
ret[name] = default[name] | |
add_to_ret(config.get, "subreddit") | |
add_to_ret(config.getboolean, "nsfw") | |
add_to_ret(config.getint, "display") | |
add_to_ret(config.get, "time") | |
add_to_ret(config.get, "output") | |
return ret | |
except IOError as e: | |
return default | |
config = load_config() | |
def parse_args(): | |
"""parse args with argparse | |
:returns: args | |
""" | |
parser = argparse.ArgumentParser(description="Daily Reddit Wallpaper") | |
parser.add_argument("-s", "--subreddit", type=str, default=config["subreddit"], | |
help="Example: art, getmotivated, wallpapers, ...") | |
parser.add_argument("-t", "--time", type=str, default=config["time"], | |
help="Example: new, hour, day, week, month, year") | |
parser.add_argument("-n", "--nsfw", action='store_true', default=config["nsfw"], help="Enables NSFW tagged posts.") | |
parser.add_argument("-d", "--display", type=int, default=config["display"], | |
help="Desktop display number on OS X (0: all displays, 1: main display, etc") | |
parser.add_argument("-o", "--output", type=str, default=config["output"], | |
help="Set the outputfolder in the home directory to save the Wallpapers to.") | |
args = parser.parse_args() | |
if args.nsfw == 'False': | |
args.nsfw = False | |
if args.nsfw == 'True': | |
args.nsfw = True | |
return args | |
class Object(object): | |
pass | |
def get_top_image(sub_reddit, save_location, blacklist, session): | |
"""Get image link of most upvoted wallpaper of the day | |
:sub_reddit: name of the sub reddit | |
:return: the image link | |
""" | |
submissions = sub_reddit.get_new(limit=30) if args.time == "new" else sub_reddit.get_top(params={"t": args.time}, limit=10) | |
#spoof for testing | |
#submissions = [Object()] | |
#submissions[0].over_18 = False | |
#submissions[0].ups = 5 | |
#submissions[0].url = u'http://dr-pen.deviantart.com/art/Bronze-Pipes-After-Mariagat-no2-666032228' | |
#submissions[0].id = u'5yx9mk' | |
#submissions[0].author = u'' | |
for submission in submissions: | |
if ( | |
(submission.over_18 and not args.nsfw) or | |
submission.ups < 5 or | |
(str(submission.author) in blacklist) | |
): | |
continue | |
ret = {"id": submission.id} | |
#print(submission) | |
url = submission.url | |
print(url) | |
if re.search("wallpapervn.com.*/download$|i.reddituploads.com|i.imgur.com|[.](jpe?g|png)($|[?#])", url, re.IGNORECASE): | |
ret["url"] = url | |
elif re.search("imgur.com.*/(a|gallery)/", url, re.IGNORECASE): | |
try: | |
images = re.findall(r"src=\"([^\"]*)\"[^>]*\"contentURL\"", session.get(url).content.decode("utf-8")); | |
saved = sorted(glob.glob(save_location + submission.id + "-" + "*")) | |
next = 0 | |
if len(saved) < len(images): | |
next = len(saved) | |
if next > 0: | |
os.rename(saved[next - 1], re.sub("!([.][^.]+|)$", r"\1", saved[next - 1])) | |
else: | |
for index, image in enumerate(saved): | |
if re.search("!([.][^.]+)?$", image): | |
os.rename(image, re.sub("!([.][^.]+|)$", r"\1", image)) | |
next = (index + 1) % len(saved) | |
break | |
try: | |
os.rename(saved[next], re.sub("(-[0-9]+)!?([.][^.]+|)$", r"\1!\2", saved[next])) | |
except ValueError as e: | |
sys.stderr.write(saved[next]) | |
raise e | |
ret["id"] = ret["id"] + "-" + str(next) + "!" | |
ret["url"] = r"http:" + images[next] | |
except ValueError as e: | |
continue | |
elif "wallpapervn.com" in url: | |
ret["url"] = url + "/download" | |
elif "uhdwallpapers.org" in url: | |
try: | |
ret["url"] = re.findall(r"down_res\" href=\"([^\"]*)\"", session.get(url).content.decode("utf-8"))[0]; | |
except ValueError as e: | |
continue | |
elif "itsoncraft.com" in url: | |
try: | |
ret["url"] = re.findall(r"property=\"og:image\" content=\"([^\"]*)\"", session.get(url, headers=headers).content.decode("utf-8"))[0]; | |
except ValueError as e: | |
continue | |
#works in the browser, but not in python, they're doing something shiftier than cookies | |
#elif "deviantart.com/art/" in url: | |
# try: | |
# ret["url"] = re.findall(r"dev-page-download[^=>]*href=\"([^\"]*)\"", session.get(url).content.decode("utf-8"))[0]; | |
# except ValueError as e: | |
# continue | |
elif "tumblr.com/post/" in url: | |
url = re.sub("/post/([^/]*)(/.*)?$", r"/image/\1", url) | |
try: | |
ret["url"] = re.findall(r"id=\"content-image\"[^>]*data-src=\"([^\"]*)\"", session.get(url).content.decode("utf-8"))[0]; | |
except ValueError as e: | |
continue | |
elif "tumblr.com/image/" in url: | |
try: | |
ret["url"] = re.findall(r"id=\"content-image\"[^>]*data-src=\"([^\"]*)\"", session.get(url).content.decode("utf-8"))[0]; | |
except ValueError as e: | |
continue | |
# Imgur support | |
elif "imgur.com" in url: | |
if url.endswith("/new"): | |
url = url.rsplit("/", 1)[0] | |
ret["url"] = "http://i.imgur.com/{id}.jpg?fake".format(id=url.rsplit("/", 1)[1].rsplit(".", 1)[0]) | |
else: | |
continue | |
if re.search("[.]gifv?([#?][^/]*)?$", ret["url"], re.IGNORECASE): | |
continue | |
return ret | |
#if args.time == "day": | |
# args.time = "week" | |
#elif args.time == "week": | |
# args.time = "month" | |
#elif args.time == "month": | |
# args.time = "new" | |
#else: | |
# return {"": 0} | |
#return get_top_image(sub_reddit) | |
return {"": 0} | |
def detect_desktop_environment(): | |
"""Get current Desktop Environment | |
http://stackoverflow.com | |
/questions/2035657/what-is-my-current-desktop-environment | |
:return: environment | |
""" | |
environment = {} | |
#if os.environ.get("KDE_FULL_SESSION") == "true": | |
environment["name"] = "kde" | |
environment["command"] = """ | |
qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript ' | |
var allDesktops = desktops(); | |
for (i=0;i<allDesktops.length;i++) {{ | |
d = allDesktops[i]; | |
d.wallpaperPlugin = "org.kde.image"; | |
d.currentConfigGroup = Array("Wallpaper", | |
"org.kde.image", | |
"General"); | |
d.writeConfig("Image", "file:///{save_location}") | |
d.writeConfig("Color", "{colour}") | |
d.writeConfig("FillMode", "1") | |
}} | |
' | |
""" | |
#elif os.environ.get("GNOME_DESKTOP_SESSION_ID"): | |
# environment["name"] = "gnome" | |
# environment["command"] = "gsettings set org.gnome.desktop.background picture-uri file://{save_location}" | |
#elif os.environ.get("DESKTOP_SESSION") == "Lubuntu": | |
# environment["name"] = "lubuntu" | |
# environment["command"] = "pcmanfm -w {save_location} --wallpaper-mode=fit" | |
#elif os.environ.get("DESKTOP_SESSION") == "mate": | |
# environment["name"] = "mate" | |
# environment["command"] = "gsettings set org.mate.background picture-filename {save_location}" | |
#else: | |
# try: | |
# info = subprocess.getoutput("xprop -root _DT_SAVE_MODE") | |
# if ' = "xfce4"' in info: | |
# environment["name"] = "xfce" | |
# except (OSError, RuntimeError): | |
# environment = None | |
# pass | |
return environment | |
if __name__ == '__main__': | |
args = parse_args() | |
subreddit = args.subreddit | |
save_dir = args.output | |
session = requests.Session() | |
supported_linux_desktop_envs = ["gnome", "mate", "kde", "lubuntu"] | |
# Python Reddit Api Wrapper | |
r = praw.Reddit(user_agent="Get top wallpaper from /r/{subreddit} by /u/ssimunic".format(subreddit=subreddit)) | |
if (os.path.exists(save_dir + "/blacklist")): | |
blacklist = [line.rstrip('\n') for line in open(save_dir + "/blacklist", "r")] | |
save_location = "{save_dir}/{subreddit}/".format( | |
save_dir = save_dir, | |
subreddit = subreddit | |
) | |
if not os.path.exists(save_location): | |
os.makedirs(save_location) | |
# Get top image link | |
image = get_top_image(r.get_subreddit(subreddit), save_location, blacklist, session) | |
if "url" in image: | |
# Request image | |
print(image["url"]) | |
save_location = save_location + image["id"] | |
if not re.search("[?]fake|^.*/[^/?#.]*([?#].*)?$", image["url"], re.IGNORECASE): | |
save_location = save_location + re.sub("^.*/[^/?#]*([.][A-Za-z0-9]*)([?#].*)?$", r"\1", image["url"]) | |
print(save_location) | |
if not os.path.isfile(save_location): | |
response = session.get(image["url"], allow_redirects=False) | |
# If image is available, proceed to save | |
if response.status_code == requests.codes.ok: | |
# Create folders if they don't exist | |
dir = os.path.dirname(save_location) | |
if not os.path.exists(dir): | |
os.makedirs(dir) | |
# Write to disk | |
with open(save_location, "wb") as fo: | |
for chunk in response.iter_content(4096): | |
fo.write(chunk) | |
else: | |
sys.exit("Error: Image url is not available, the program is now exiting.") | |
else: | |
save_location = glob.glob(save_location + "*") | |
random.shuffle(save_location) | |
if len(save_location) < 1: | |
sys.exit("Error: No previous images from that subreddit to fallback to") | |
save_location = random.sample(save_location, 1)[0] | |
# Check OS and environments | |
platform_name = platform.system() | |
if platform_name.startswith("Lin"): | |
# Check desktop environments for linux | |
desktop_environment = detect_desktop_environment() | |
if desktop_environment and desktop_environment["name"] in supported_linux_desktop_envs: | |
colour = os.popen("convert '{save_location}' -resize 1x1 txt: | grep -oP '#[A-Z0-9]{{6}}'".format(save_location=save_location)).read().splitlines()[0] | |
os.system(desktop_environment["command"].format(save_location=save_location, colour=colour)) | |
else: | |
print("Unsupported desktop environment") | |
# Windows | |
if platform_name.startswith("Win"): | |
# Python 3.x | |
if sys.version_info >= (3, 0): | |
ctypes.windll.user32.SystemParametersInfoW(20, 0, save_location, 3) | |
# Python 2.x | |
else: | |
ctypes.windll.user32.SystemParametersInfoA(20, 0, save_location, 3) | |
# OS X/macOS | |
if platform_name.startswith("Darwin"): | |
if args.display == 0: | |
command = """ | |
osascript -e 'tell application "System Events" | |
set desktopCount to count of desktops | |
repeat with desktopNumber from 1 to desktopCount | |
tell desktop desktopNumber | |
set picture to "{save_location}" | |
end tell | |
end repeat | |
end tell' | |
""".format(save_location=save_location) | |
else: | |
command = """osascript -e 'tell application "System Events" | |
set desktopCount to count of desktops | |
tell desktop {display} | |
set picture to "{save_location}" | |
end tell | |
end tell'""".format(display=args.display, | |
save_location=save_location) | |
os.system(command) |
This file contains hidden or 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
BackgroundArt | |
BirdsForScale | |
CityPorn | |
Cyberpunk | |
earthporn | |
ImaginaryArchitecture | |
ImaginaryCityscapes | |
ImaginaryFuturism | |
ImaginaryLandscapes | |
ImaginaryMindscapes | |
spaceporn | |
SpecArt | |
tiltshift | |
ultrahdwallpapers | |
VillagePorn | |
wallpaper | |
wallpapers | |
WQHD_Wallpaper |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A modified version of a basic script I found online (for some reason there's no mention of from where/who).
Set this up in a 30min cron
Additions include:
subs.x
file (wherex
is a number; it renames thex
to reflect the next sub to look at)blacklist
fileNB requires version 3.5 of praw, it scrapes reddit and doesn't need an API token