#!/usr/bin/env python3 # Eryn Wells ''' New script. ''' import argparse import datetime import os import os.path import shutil import subprocess from PIL import Image from PIL.ExifTags import TAGS from typing import Optional from website.metadata import slugify PHOTOS_CONTENT_DIR = 'content/photos' def parse_args(argv, *a, **kw): parser = argparse.ArgumentParser(*a, **kw) parser.add_argument('-e', '--edit', action='store_true') parser.add_argument('-n', '--dry-run', action='store_true') parser.add_argument('-t', '--title') parser.add_argument('-s', '--slug') parser.add_argument('--dump-exif', action='store_true') parser.add_argument('photos', nargs='+') args = parser.parse_args(argv) return args def main(argv): args = parse_args(argv[1:], prog=argv[0]) earliest_exif_date: Optional[datetime.datetime] = None for index, photo in enumerate(args.photos): print(f'image\t\t{photo}') try: image = Image.open(photo) except IOError: continue raw_exif = image._getexif() friendly_exif = {TAGS[k]: v for k, v in raw_exif.items() if k in TAGS} try: date_string = f'{friendly_exif["DateTime"]} {friendly_exif["OffsetTime"]}' exif_date = datetime.datetime.strptime(date_string, '%Y:%m:%d %H:%M:%S %z') except KeyError: exif_date = datetime.datetime.strptime(friendly_exif["DateTime"], '%Y:%m:%d %H:%M:%S') print(f'capture-time\t{exif_date.isoformat()}') iso_rating = friendly_exif.get('ISOSpeedRatings') if iso_rating: print(f'iso\t\t{iso_rating}') focal_length_35mm = friendly_exif.get('FocalLengthIn35mmFilm') focal_length = friendly_exif.get('FocalLength') if focal_length or focal_length_35mm: print(f'focal-length\t{focal_length} {focal_length_35mm}') fstop = friendly_exif.get('FNumber') if fstop: print(f'f-stop\t\t{fstop}') exposure_time = friendly_exif.get('ExposureTime') if exposure_time: print(f'exposure-time\t{exposure_time}') if not earliest_exif_date or exif_date < earliest_exif_date: earliest_exif_date = exif_date if index < len(args.photos) - 1: print() if not earliest_exif_date: earliest_exif_date = datetime.datetime.now() year = earliest_exif_date.year month = earliest_exif_date.month if args.slug: name = args.slug elif args.title: name = slugify(args.title) else: name = os.path.splitext(os.path.basename(photo))[0] post_path_year = os.path.join(PHOTOS_CONTENT_DIR, f'{year:04}', name) post_path_year_month = os.path.join(PHOTOS_CONTENT_DIR, f'{year:04}', f'{month:02}', name) if os.path.exists(post_path_year): if os.path.exists(post_path_year_month): print("Couldn't find path for photo post. Both of the following paths exist.", file=sys.stderr) print(f' {post_path_year}', file=sys.stderr) print(f' {post_path_year_month}', file=sys.stderr) return -1 else: post_path = post_path_year_month else: post_path = post_path_year try: hugo_command = ['hugo', 'new', '--clock', earliest_exif_date.isoformat(), post_path] if not args.dry_run: result = subprocess.run(hugo_command) result.check_returncode() else: print(' '.join(hugo_command), file=sys.stderr) except subprocess.CalledProcessError: print(f'Failed to create new Hugo post', file=sys.stderr) return -1 index_file_path = os.path.join(post_path, 'index.md') if args.title and not args.dry_run: # The hugo command can't set a title for a post so I need to do it myself. with open(index_file_path) as index_file: index_file_contents = index_file.readlines() for i in range(len(index_file_contents)): line = index_file_contents[i] if not line.startswith('title:'): continue updated_line = f'title: "{args.title}"\n' index_file_contents[i] = updated_line with open(index_file_path, 'w') as index_file: index_file.writelines(index_file_contents) if not args.dry_run and args.edit: editor = os.environ.get('EDITOR', 'vi') subprocess.run([editor, index_file_path], shell=True) for photo in args.photos: print(f'Copy {photo} -> {post_path}') try: if not args.dry_run: shutil.copy(photo, post_path) except IOError: print(f'Failed to copy {photo}', file=sys.stderr) return -2 if __name__ == '__main__': import sys result = main(sys.argv) sys.exit(0 if not result else result)