Skip to content

Commit

Permalink
add option to use globally unique filenames
Browse files Browse the repository at this point in the history
  • Loading branch information
tymmej committed Aug 29, 2023
1 parent 3a1c89c commit 6624e46
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ photos:
remove_obsolete: false
sync_interval: 500
all_albums: false # Optional, default false. If true preserve album structure. If same photo is in multpile albums creates duplicates on filesystem
# Optional, default false. If true all files have globally unique filenames, it should matter when all_albums is true and one photo is in pultpile album
unique_filenames: false
filters:
# if all_albums is false list of albums to download, if all_albums is true list of ignored albums
# if empty and all_albums is false download all photos to "all" folder. if empty and all_albums is true download all folders
Expand Down
10 changes: 10 additions & 0 deletions src/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ def get_photos_all_albums(config):
return download_all


def get_photos_unique_file_names(config):
"""Return flag to use unique filenames."""
unique_filenames = False
config_path = ["photos", "unique_filenames"]
if traverse_config_path(config=config, config_path=config_path):
unique_filenames = get_config_value(config=config, config_path=config_path)
LOGGER.info("Using unique filenames.")
return unique_filenames


def prepare_root_destination(config):
"""Prepare root destination."""
LOGGER.debug("Checking root destination ...")
Expand Down
30 changes: 24 additions & 6 deletions src/sync_photos.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def photo_wanted(photo, extensions):
return False


def generate_file_name(photo, file_size, destination_path):
def generate_file_name(photo, file_size, destination_path, unique_file_names):
"""Generate full path to file."""
filename = photo.filename
name, extension = filename.rsplit(".", 1) if "." in filename else [filename, ""]
Expand All @@ -48,7 +48,20 @@ def generate_file_name(photo, file_size, destination_path):
os.rename(file_size_path, file_size_id_path)
if os.path.isfile(file_size_id_path):
os.rename(file_size_id_path, file_size_id_path_norm)
return file_size_id_path_norm

photo_file_name = file_size_id_path_norm

if unique_file_names:
album_name = destination_path.split("/")[-1]
file_size_id_album_name_short_path = os.path.join(
destination_path,
f'{"__".join([album_name, name, file_size, base64.urlsafe_b64encode(photo.id.encode()).decode()[2:10]])}.{extension}',
)
photo_file_name = unicodedata.normalize("NFC", file_size_id_album_name_short_path)
if os.path.isfile(file_size_id_path_norm):
os.rename(file_size_id_path_norm, photo_file_name)

return photo_file_name


def photo_exists(photo, file_size, local_path):
Expand Down Expand Up @@ -83,10 +96,10 @@ def download_photo(photo, file_size, destination_path):
return True


def process_photo(photo, file_size, destination_path, files):
def process_photo(photo, file_size, destination_path, files, unique_file_names):
"""Process photo details."""
photo_path = generate_file_name(
photo=photo, file_size=file_size, destination_path=destination_path
photo=photo, file_size=file_size, destination_path=destination_path, unique_file_names=unique_file_names
)
if file_size not in photo.versions:
LOGGER.warning(
Expand All @@ -101,7 +114,7 @@ def process_photo(photo, file_size, destination_path, files):
return True


def sync_album(album, destination_path, file_sizes, extensions=None, files=None):
def sync_album(album, destination_path, file_sizes, extensions=None, files=None, unique_file_names=False):
"""Sync given album."""
if album is None or destination_path is None or file_sizes is None:
return None
Expand All @@ -110,7 +123,7 @@ def sync_album(album, destination_path, file_sizes, extensions=None, files=None)
for photo in album:
if photo_wanted(photo, extensions):
for file_size in file_sizes:
process_photo(photo, file_size, destination_path, files)
process_photo(photo, file_size, destination_path, files, unique_file_names)
else:
LOGGER.debug(f"Skipping the unwanted photo {photo.filename}.")
for subalbum in album.subalbums:
Expand All @@ -120,6 +133,7 @@ def sync_album(album, destination_path, file_sizes, extensions=None, files=None)
file_sizes,
extensions,
files,
unique_file_names=unique_file_names,
)
return True

Expand All @@ -145,6 +159,7 @@ def sync_photos(config, photos):
filters = config_parser.get_photos_filters(config=config)
files = set()
download_all = config_parser.get_photos_all_albums(config=config)
unique_file_names = config_parser.get_photos_unique_file_names(config=config)
if download_all:
for album in photos.albums.keys():
if album in iter(filters["albums"]):
Expand All @@ -155,6 +170,7 @@ def sync_photos(config, photos):
file_sizes=filters["file_sizes"],
extensions=filters["extensions"],
files=files,
unique_file_names=unique_file_names,
)
elif filters["albums"]:
for album in iter(filters["albums"]):
Expand All @@ -164,6 +180,7 @@ def sync_photos(config, photos):
file_sizes=filters["file_sizes"],
extensions=filters["extensions"],
files=files,
unique_file_names=unique_file_names,
)
else:
sync_album(
Expand All @@ -172,6 +189,7 @@ def sync_photos(config, photos):
file_sizes=filters["file_sizes"],
extensions=filters["extensions"],
files=files,
unique_file_names=unique_file_names,
)

if config_parser.get_photos_remove_obsolete(config=config):
Expand Down

0 comments on commit 6624e46

Please sign in to comment.