Skip to content

Instantly share code, notes, and snippets.

@Hashbrown777
Created February 9, 2020 08:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hashbrown777/bb1d4dd2b8a1c41af12054998b1813bf to your computer and use it in GitHub Desktop.
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
#!/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)
BackgroundArt
BirdsForScale
CityPorn
Cyberpunk
earthporn
ImaginaryArchitecture
ImaginaryCityscapes
ImaginaryFuturism
ImaginaryLandscapes
ImaginaryMindscapes
spaceporn
SpecArt
tiltshift
ultrahdwallpapers
VillagePorn
wallpaper
wallpapers
WQHD_Wallpaper
@Hashbrown777
Copy link
Author

Hashbrown777 commented Feb 9, 2020

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:

  • cycles through a number of subreddits defined in a subs.x file (where x is a number; it renames the x to reflect the next sub to look at)
  • on plasma it sets the background colour to the average colour of the downloaded image, so when the image doesn't fit the ratio of the screen/s it has a nice bezel
  • images fit, not fill, the screen
  • images are only downloaded if not already previously
  • skips posts created by users mentioned in a blacklist file
  • only considers posts that are both nonNSFW and have 5+ upvotes (for slowmoving subs as a way to fight bots/unreported NSFW posts)

NB requires version 3.5 of praw, it scrapes reddit and doesn't need an API token

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment