Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unique filenames #148

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ 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
unique_filenames: false # Optional, default false. If true all files have globally unique filenames, it should matter when filter > albums is empty and one photo is in multiple album
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
9 changes: 9 additions & 0 deletions src/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ 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
50 changes: 44 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,28 @@ 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 = [
album_name,
name,
file_size,
base64.urlsafe_b64encode(photo.id.encode()).decode()[2:10],
]
file_size_id_album_name_short_path = os.path.join(
destination_path,
f'{"__".join(file_size_id_album_name)}.{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 +104,13 @@ 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 +125,14 @@ 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 +141,9 @@ 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 +153,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 +179,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():
sync_album(
Expand All @@ -153,6 +188,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 @@ -162,6 +198,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 @@ -170,6 +207,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
2 changes: 2 additions & 0 deletions tests/test_sync_photos.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ def versions(self):
file_size="medium",
destination_path=self.destination_path,
files=None,
unique_file_names=False,
)
)

Expand All @@ -516,6 +517,7 @@ def versions(self):
file_size="thumb",
destination_path=self.destination_path,
files=None,
unique_file_names=False,
)
)

Expand Down
Loading