| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- #!/usr/bin/python3
- from typing import List, Optional
- from pydantic import BaseModel
- import yaml
- import shutil
- import zipfile
- import os
- import sys
- from datetime import datetime as dt
- # ----
- yaml_filename = 'galleries.yaml'
- content_dir = "./content"
- zip_dir = "./downloads"
- # ----
- def makeThankYou(gallery:str, date_generated:str):
- return """Thank you for purchasing the "%s" gallery from larsee.com/photography!
- By purchasing this product you are granted a license to use the images for any purpose.
- This archive was generated: %s. In the future the gallery contents might change.
- Don't hesitate to contact me if you have questions or other inquiries. This is my private email: lars@f-w.dk
- Sincerely,
- Lars Ole Pontoppidan
- """ % (gallery, date_generated)
- # ----
- class Gallery(BaseModel):
- folder_name: str
- title: str
- description: Optional[str] = None
- cover_photo: Optional[str] = None
- photos: List[str]
- class Galleries(BaseModel):
- picture_root: str
- galleries: List[Gallery]
- def loadGalleries(yaml_file_path: str) -> Galleries:
- with open(yaml_file_path, 'r') as file:
- data = yaml.safe_load(file)
- return Galleries(**data)
- def fileTitle(s:str) -> str:
- sp = s.split("/")
- return sp[-1]
- class Photo():
- def __init__(self, photo_root:str, source_file:str, prefix:str, index:int):
- sp = source_file.split("/")
- self.photoPath = sp[0]
- self.photoName = sp[1]
- self.destName = prefix + "_%02d.jpg" % index
- self.photoRoot = photo_root
-
- def getDestJpgName(self):
- return self.destName
-
- def getHqFileSource(self):
- return os.path.join(self.photoRoot, self.photoPath, "hq", self.photoName + "_hq.jpg")
- def getRawFilePath(self):
- opt1 = os.path.join(self.photoRoot, self.photoPath, self.photoName + ".NEF")
- opt2 = os.path.join(self.photoRoot, self.photoPath, self.photoName + ".JPG")
- if os.path.isfile(opt1):
- return opt1
- elif os.path.isfile(opt2):
- return opt2
- else:
- raise Exception("Can't find source file for: " + self.photoName)
-
- def getPp3FilePath(self):
- return self.getRawFilePath() + ".pp3"
-
- def getTifFilePath(self):
- return os.path.join(self.photoRoot, self.photoPath, "converted", self.photoName + ".tif")
- class PhotosInGallery():
- def __init__(self, photo_root:str, gallery:Gallery):
- self.photos:List[Photo] = []
- self.cover_photo:Optional[Photo] = None
- for idx, photo in enumerate(gallery.photos, start=1):
- p = Photo(photo_root, photo, gallery.folder_name, idx)
- self.photos.append(p)
- if photo == gallery.cover_photo:
- self.cover_photo = p
-
- def makeIndexFile(weight:int, weight_rev:int, gallery:Gallery, photos:PhotosInGallery):
- values = {
- "title" : gallery.title,
- "weight" : weight,
- "menus" : {"main" : {"weight" : weight_rev}},
- }
- if gallery.description is not None:
- values["description"] = gallery.description
- if photos.cover_photo is not None:
- values["featured_image"] = photos.cover_photo.getDestJpgName()
- return "---\n" + yaml.dump(values, default_flow_style=False) + "---\n"
- def makeGalleries(yaml_root:Galleries):
- print("Purging old galleries")
- for item in os.listdir(content_dir):
- item_path = os.path.join(content_dir, item)
- if os.path.isdir(item_path):
- print(f" deleting folder: {item_path}")
- shutil.rmtree(item_path)
- print("Setting up galleries")
- for idx, gallery in enumerate(yaml_root.galleries):
- path = os.path.join(content_dir, gallery.folder_name)
- weight = len(yaml_root.galleries) - idx
- print(" making dir: " + path)
- os.makedirs(path, exist_ok=True)
- photos = PhotosInGallery(yaml_root.picture_root, gallery)
- index = makeIndexFile(weight, idx + 1, gallery, photos)
- with open(os.path.join(path, "index.md"), "w") as f:
- f.write(index)
- # Link in the pictures
- for photo in photos.photos:
- #os.symlink(photo.getHqFileSource(), os.path.join(path, photo.getSimpleJpgName()))
- shutil.copyfile(photo.getHqFileSource(), os.path.join(path, photo.getDestJpgName()))
- def makeZipDownloads(yaml_root:Galleries):
-
- if os.path.isdir(zip_dir):
- print("Purging old downloads")
- shutil.rmtree(zip_dir)
-
- os.makedirs(zip_dir, exist_ok=True)
- # Get the current date and time
- dt_now = dt.now()
- print("Making download zips, archive date: " + dt_now.strftime("%B %d, %Y"))
- for gallery in yaml_root.galleries:
- photos = PhotosInGallery(yaml_root.picture_root, gallery)
- # Create a ZIP file for the gallery
- zip_path = os.path.join(zip_dir, "Gallery %s.zip" % gallery.folder_name)
- print(" making zip: " + zip_path)
- #gallery_folder = "%s_%s" % (gallery.folder_name, dt_now.strftime("%b_%d_%Y"))
- gallery_folder = gallery.folder_name
- with zipfile.ZipFile(zip_path, 'w') as myzip:
- def addToZip(path:str, sub_folder:Optional[str] = None):
- if sub_folder is None:
- myzip.write(path, os.path.join(gallery_folder, os.path.basename(path)))
- else:
- myzip.write(path, os.path.join(gallery_folder, sub_folder, os.path.basename(path)))
- for photo in photos.photos:
- addToZip(photo.getRawFilePath())
- addToZip(photo.getPp3FilePath())
- addToZip(photo.getTifFilePath(), "converted")
-
- myzip.writestr('Thank you.txt', makeThankYou(gallery.title, dt_now.strftime("%B %d, %Y")))
- def main(galleries:bool, zips:bool):
- print("Loading " + yaml_filename)
- yaml_root = loadGalleries(yaml_filename)
- if galleries:
- makeGalleries(yaml_root)
- if zips:
- makeZipDownloads(yaml_root)
- def usage():
- print("""
- Usage:
- make_galleries OPTIONS
-
- Options:
- -g Make galleries
- -z Make download zips
- """)
-
- if __name__ == "__main__":
- zips = "-z" in sys.argv
- galleries = "-g" in sys.argv
- if zips == False and galleries == False:
- usage()
- else:
- main(galleries, zips)
|