Add functionality for rest of settings

This commit is contained in:
Isaac Shoebottom 2024-11-20 18:22:46 -04:00
parent 19dd251165
commit 90dc4b78f1
5 changed files with 118 additions and 21 deletions

View File

@ -6,26 +6,47 @@ import importlib
import logging import logging
import slugify import slugify
import settings import settings
import time
import croniter
def main(): def main():
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
config = settings.load_settings() config = settings.load_settings()
logging.basicConfig(level=config['general']['log_level'], format="%(asctime)s [%(levelname)s] %(message)s", force=True)
logging.debug(f"Config: {config}") logging.debug(f"Config: {config}")
chosen_providers = config['general']['provider']
# Daemon mode
if config['daemon']['daemon']:
while True:
for provider in chosen_providers:
download_with_provider(provider, config)
if config['daemon']['cron'] != "":
now = datetime.datetime.now()
cron = croniter.croniter(config['daemon']['cron'], now)
next_run = cron.get_next(datetime.datetime)
logging.info(f"Next run: {next_run}")
time.sleep((next_run - now).total_seconds())
else:
time.sleep(config['daemon']['interval'])
# Download once
else:
for provider in chosen_providers:
download_with_provider(provider, config)
def download_with_provider(provider_name, config):
session = requests.Session() session = requests.Session()
session.headers.update({ session.headers.update({
"User-Agent": config['general']['user_agent'] "User-Agent": config['general']['user_agent']
}) })
# Convenience variables, could be inlined # Convenience variables, could be inlined
provider_name = config['general']['provider'] provider_settings = config[provider_name] if provider_name in config else None
provider_settings = config[config['general']['provider']]
download_location = os.path.abspath(os.path.expanduser(config['general']['location'])) download_location = os.path.abspath(os.path.expanduser(config['general']['location']))
# Load the provider module # Load the provider module
provider = importlib.import_module(f"providers.{config['general']['provider']}") provider = importlib.import_module(f"providers.{provider_name}")
# Create an instance of the provider # Create an instance of the provider
provider_obj = getattr(provider, provider_name.title())(provider_settings, session) provider_obj = getattr(provider, provider_name.title())(provider_settings, session)
@ -33,17 +54,25 @@ def main():
image_url, image_title = provider_obj.get_image_info() image_url, image_title = provider_obj.get_image_info()
logging.debug(f"Image URL: {image_url}") logging.debug(f"Image URL: {image_url}")
# Download the image # Variables for the file path
image = session.get(image_url).content date = datetime.datetime.now().strftime("%Y-%m-%d")
image_title = slugify.slugify(image_title)
file_path = f"{download_location}/{provider_name.title()}/{date} [{image_title}].jpg"
# Check if we should include the title in the filename
if not config['general']['include_title']:
file_path = f"{download_location}/{provider_name.title()}/{date}.jpg"
# Create the download location if it doesn't exist
if not os.path.exists(download_location): if not os.path.exists(download_location):
os.mkdir(download_location) os.mkdir(download_location)
if not os.path.exists(f"{download_location}/{provider_name.title()}"): if not os.path.exists(f"{download_location}/{provider_name.title()}"):
os.mkdir(f"{download_location}/{provider_name.title()}") os.mkdir(f"{download_location}/{provider_name.title()}")
# Check if the file exists and if we should overwrite it
if os.path.exists(file_path) and not config['general']['overwrite']:
return
date = datetime.datetime.now().strftime("%Y-%m-%d") # Download the image
image_title = slugify.slugify(image_title) image = session.get(image_url).content
with open(f"{download_location}/{provider_name.title()}/{date} [{image_title}].jpg", "wb") as file: with open(file_path, "wb") as file:
file.write(image) file.write(image)
if __name__ == "__main__": if __name__ == "__main__":

53
poetry.lock generated
View File

@ -125,6 +125,21 @@ files = [
{file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"},
] ]
[[package]]
name = "croniter"
version = "5.0.1"
description = "croniter provides iteration for datetime object with cron like format"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.6"
files = [
{file = "croniter-5.0.1-py2.py3-none-any.whl", hash = "sha256:eb28439742291f6c10b181df1a5ecf421208b1fc62ef44501daec1780a0b09e9"},
{file = "croniter-5.0.1.tar.gz", hash = "sha256:7d9b1ef25b10eece48fdf29d8ac52f9b6252abff983ac614ade4f3276294019e"},
]
[package.dependencies]
python-dateutil = "*"
pytz = ">2021.1"
[[package]] [[package]]
name = "idna" name = "idna"
version = "3.10" version = "3.10"
@ -139,6 +154,20 @@ files = [
[package.extras] [package.extras]
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"
description = "Extensions to the standard Python datetime module"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
files = [
{file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
{file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
]
[package.dependencies]
six = ">=1.5"
[[package]] [[package]]
name = "python-slugify" name = "python-slugify"
version = "8.0.4" version = "8.0.4"
@ -156,6 +185,17 @@ text-unidecode = ">=1.3"
[package.extras] [package.extras]
unidecode = ["Unidecode (>=1.1.1)"] unidecode = ["Unidecode (>=1.1.1)"]
[[package]]
name = "pytz"
version = "2024.2"
description = "World timezone definitions, modern and historical"
optional = false
python-versions = "*"
files = [
{file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"},
{file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"},
]
[[package]] [[package]]
name = "requests" name = "requests"
version = "2.32.3" version = "2.32.3"
@ -177,6 +217,17 @@ urllib3 = ">=1.21.1,<3"
socks = ["PySocks (>=1.5.6,!=1.5.7)"] socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
[[package]] [[package]]
name = "text-unidecode" name = "text-unidecode"
version = "1.3" version = "1.3"
@ -218,4 +269,4 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.11" python-versions = "^3.11"
content-hash = "cbcfeef2301c00347932493e38948d8930eb3e2a1cc65f1781d86d50614ac3f6" content-hash = "65c5d981b2146aee4317e6d04fc32e949094e70be5dd7a26f44c76614a92ee33"

View File

@ -13,7 +13,7 @@ class Unsplash(Provider):
super().__init__(settings, session) super().__init__(settings, session)
def get_image_info(self): def get_image_info(self):
query = "https://unsplash.com/collections/1459961/photo-of-the-day-(archive)" query = f"https://unsplash.com/collections/{self.settings['collection']}"
logging.debug(f"Query: {query}") logging.debug(f"Query: {query}")
response = self.session.get(query).text response = self.session.get(query).text

View File

@ -11,6 +11,7 @@ requests = "^2.32"
urllib3 = "^1.26" urllib3 = "^1.26"
python-slugify = "^8.0" python-slugify = "^8.0"
tomlkit = "^0.13.2" tomlkit = "^0.13.2"
croniter = "^5.0"
[build-system] [build-system]

View File

@ -1,3 +1,4 @@
import logging
import os.path import os.path
import tomlkit import tomlkit
@ -6,20 +7,14 @@ user_path = os.path.expanduser("~/.config/daily-wallpaper/config.toml")
def default_settings(): def default_settings():
general = tomlkit.table() general = tomlkit.table()
general.add("interval", 86400)
general["interval"].comment("Interval in seconds (24 hours)")
general.add("start", 7200)
general["start"].comment("Start time in seconds (2:00 AM)")
general.add("location", "~/Pictures/Wallpapers") general.add("location", "~/Pictures/Wallpapers")
general["location"].comment("Download location") general["location"].comment("Download location")
general.add("provider", "bing") general.add("provider", ["bing", "unsplash", "wikimedia"])
general["provider"].comment("Which wallpaper provider to use") general["provider"].comment("Which wallpaper provider to use, in order of preference (do no include if you don't want to download the file)")
general.add("include_title", True) general.add("include_title", True)
general.value.item("include_title").comment("Include image title in filename") general.value.item("include_title").comment("Include image title in filename")
general.add("set_wallpaper", False) general.add("set_wallpaper", False)
general.value.item("set_wallpaper").comment("Set wallpaper after download") general.value.item("set_wallpaper").comment("Set wallpaper after download")
general.add("daemon", False)
general.value.item("daemon").comment("Run as daemon (continuously in the background)")
general.add("log", False) general.add("log", False)
general.value.item("log").comment("Log to file, located in the download location") general.value.item("log").comment("Log to file, located in the download location")
general.add("log_level", "INFO") general.add("log_level", "INFO")
@ -30,6 +25,15 @@ def default_settings():
general["user_agent"].comment("User-Agent to use for requests, change to avoid being blocked or to comply with ToS") general["user_agent"].comment("User-Agent to use for requests, change to avoid being blocked or to comply with ToS")
general.add(tomlkit.nl()) general.add(tomlkit.nl())
daemon = tomlkit.table()
daemon.add("daemon", False)
daemon.value.item("daemon").comment("Run as daemon (continuously in the background)")
daemon.add("interval", 86400)
daemon["interval"].comment("Interval in seconds (24 hours)")
daemon.add("cron", "0 0 * * *")
daemon["cron"].comment("Cron expression, overrides interval")
daemon.add(tomlkit.nl())
bing = tomlkit.table() bing = tomlkit.table()
bing.add("size", "UHD") bing.add("size", "UHD")
bing["size"].comment('Image size, possible values: "UHD", "1920x1080"') bing["size"].comment('Image size, possible values: "UHD", "1920x1080"')
@ -56,6 +60,7 @@ def default_settings():
defaults = tomlkit.document() defaults = tomlkit.document()
defaults.add("general", general) defaults.add("general", general)
defaults.add("daemon", daemon)
defaults.add("bing", bing) defaults.add("bing", bing)
defaults.add("unsplash", unsplash) defaults.add("unsplash", unsplash)
defaults.add("wikimedia", wikimedia) defaults.add("wikimedia", wikimedia)
@ -63,6 +68,17 @@ def default_settings():
return defaults return defaults
def load_settings(): def load_settings():
# TODO: Find a better way to do this
if os.environ.get("RAPID_DEVELOPMENT") is not None:
if os.path.exists(user_path):
os.remove(user_path)
if os.path.exists(local_path):
os.remove(local_path)
settings = default_settings()
with open(local_path, mode='w') as file:
tomlkit.dump(settings, file)
return settings
if os.path.exists(local_path): if os.path.exists(local_path):
settings = tomlkit.parse(open(local_path, mode='r').read()) settings = tomlkit.parse(open(local_path, mode='r').read())
elif os.path.exists(user_path): elif os.path.exists(user_path):