💻 Wpx is a wallpaper downloader.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
3.9 KiB

# -*- coding: utf8 -*-
# Copyright (c) 2020 Niklas Rosenstein
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
from nr.databind.core import ObjectMapper
from nr.databind.json import JsonModule
from typing import Optional, BinaryIO
from wpx.providers import IImageProvider
import argparse
import logging
import os
import sys
import yaml
logger = logging.getLogger(__name__)
mapper = ObjectMapper(JsonModule())
def save_to(filename: str, src: BinaryIO, chunk_size: int = 1024*16):
""" Saves the contents from *src* to the specified *filename*. """
with open(filename, 'wb') as dst:
while True:
chunk = src.read(chunk_size)
dst.write(chunk)
if not chunk:
break
def get_argument_parser(prog: Optional[str]):
parser = argparse.ArgumentParser(prog=prog)
parser.add_argument('provider', help='The name of the image provider.')
parser.add_argument('config', nargs='?', help='Inline JSON configuration of the provider.')
parser.add_argument('-d', '--directory', help='The output directory.')
parser.add_argument('--overwrite', action='store_true', help='Overwrite output file(s).')
parser.add_argument('--daily', action='store_true', help='Get the daily image.')
parser.add_argument('--random', action='store_true', help='Get a random image.')
parser.add_argument('--set-desktop', action='store_true', help='Set as desktop wallpaper.')
parser.add_argument('--set-login', action='store_true', help='Set as login wallpaper.')
return parser
def main(argv=None, prog=None):
logging.basicConfig(format='%(message)s', level=logging.INFO)
parser = get_argument_parser(prog)
args = parser.parse_args(argv)
if not args.daily and not args.random:
parser.error('no action specified, try --daily or --random')
if args.directory:
os.chdir(args.directory)
payload = {'type': args.provider}
payload.update(yaml.safe_load(args.config or '{}'))
provider = mapper.deserialize(payload, IImageProvider)
try:
if args.daily:
image = provider.get_daily_image()
elif args.random:
image = provider.get_random_image()
except NotImplementedError:
parser.error('{}: unsupported operation'.format(args.provider))
if args.overwrite or not os.path.isfile(image.filename):
with image.open() as src:
save_to(image.filename, src)
else:
logging.info('note: "%s" already exists', image.filename)
# Print the absolute path to the saved file so that scripts can get it.
print(os.path.abspath(image.filename))
if args.set_desktop or args.set_login:
from .setwp import SetWallpaperOptions, set_wallpaper
options = SetWallpaperOptions(image.filename,
desktop=args.set_desktop, login=args.set_login)
try:
set_wallpaper(options)
except NotImplementedError:
print('error: setting wallpaper is not supported on this system.',
file=sys.stderr)
_entry_main = lambda: exit(main())
if __name__ == '__main__':
_entry_main()