erynwells.me/scripts/new-photo-post.py

117 lines
3.5 KiB
Python
Executable file

#!env/bin/python3
# Eryn Wells <eryn@erynwells.me>
'''
New script.
'''
import argparse
import datetime
import os.path
import re
import shutil
import subprocess
from PIL import Image
from PIL.ExifTags import TAGS
PHOTOS_CONTENT_DIR = 'content/photos'
def slugify(s):
return re.sub(r'\s+', '-', s.strip().lower())
def parse_args(argv, *a, **kw):
parser = argparse.ArgumentParser(*a, **kw)
parser.add_argument('-n', '--dry-run', action='store_true')
parser.add_argument('-t', '--title')
parser.add_argument('-s', '--slug')
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 = None
for photo in args.photos:
try:
image = Image.open(photo)
except IOError:
pass
raw_exif = image._getexif()
friendly_exif = {TAGS[k]: v for k, v in raw_exif.items() if k in TAGS}
date_string = f'{friendly_exif["DateTime"]} {friendly_exif["OffsetTime"]}'
exif_date = datetime.datetime.strptime(date_string, '%Y:%m:%d %H:%M:%S %z')
print(f'{photo} -> {exif_date.isoformat()}')
if not earliest_exif_date or exif_date < earliest_exif_date:
earliest_exif_date = exif_date
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))
except subprocess.CalledProcessError:
print(f'Failed to create new Hugo post', file=sys.stderr)
return -1
if args.title:
# The hugo command can't set a title for a post so I need to do it myself.
index_file_path = os.path.join(post_path, 'index.md')
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)
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)