From 5f692314c03bfa4c4eb713f4753812ac1972d5f3 Mon Sep 17 00:00:00 2001 From: alternak Date: Wed, 1 May 2024 16:46:55 +0200 Subject: [PATCH 1/8] Add insecure ssl param --- immich_auto_album.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/immich_auto_album.py b/immich_auto_album.py index 2cd7450..a281f61 100644 --- a/immich_auto_album.py +++ b/immich_auto_album.py @@ -5,6 +5,7 @@ import logging import sys import datetime from collections import defaultdict +import urllib3 parser = argparse.ArgumentParser(description="Create Immich Albums from an external library path based on the top level folders", formatter_class=argparse.ArgumentDefaultsHelpFormatter) @@ -18,6 +19,7 @@ parser.add_argument("-s", "--album-separator", default=" ", type=str, help="Sepa parser.add_argument("-c", "--chunk-size", default=2000, type=int, help="Maximum number of assets to add to an album with a single API call") parser.add_argument("-C", "--fetch-chunk-size", default=5000, type=int, help="Maximum number of assets to fetch with a single API call") parser.add_argument("-l", "--log-level", default="INFO", choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'], help="Log level to use") +parser.add_argument("-i", "--ignore-ssl", action="store_true", help="Set to true to ignore SSL verification") args = vars(parser.parse_args()) # set up logger to log in logfmt format logging.basicConfig(level=args["log_level"], stream=sys.stdout, format='time=%(asctime)s level=%(levelname)s msg=%(message)s') @@ -31,6 +33,7 @@ number_of_assets_to_fetch_per_request = args["fetch_chunk_size"] unattended = args["unattended"] album_levels = args["album_levels"] album_level_separator = args["album_separator"] +ignore_ssl = args["ignore_ssl"] logging.debug("root_path = %s", root_paths) logging.debug("root_url = %s", root_url) logging.debug("api_key = %s", api_key) @@ -39,12 +42,16 @@ logging.debug("number_of_assets_to_fetch_per_request = %d", number_of_assets_to_ logging.debug("unattended = %s", unattended) logging.debug("album_levels = %d", album_levels) logging.debug("album_level_separator = %s", album_level_separator) +logging.debug("ignore_ssl = %s", ignore_ssl) # Verify album levels if album_levels == 0: parser.print_help() exit(1) +if ignore_ssl: + urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + # Yield successive n-sized # chunks from l. def divide_chunks(l, n): @@ -59,7 +66,8 @@ requests_kwargs = { 'x-api-key': api_key, 'Content-Type': 'application/json', 'Accept': 'application/json' - } + }, + 'verify' : not ignore_ssl } # append trailing slash to all root paths From e392f7a9d7059ce730ac83538fe59bd21636a672 Mon Sep 17 00:00:00 2001 From: Salvoxia Date: Tue, 30 Jul 2024 20:38:28 +0200 Subject: [PATCH 2/8] Renamed option for skipping SSL verification to -k/--insecure (referencing curl) --- immich_auto_album.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/immich_auto_album.py b/immich_auto_album.py index d2d19e2..a375252 100644 --- a/immich_auto_album.py +++ b/immich_auto_album.py @@ -26,7 +26,7 @@ parser.add_argument("-s", "--album-separator", default=" ", type=str, help="Sepa parser.add_argument("-c", "--chunk-size", default=2000, type=int, help="Maximum number of assets to add to an album with a single API call") parser.add_argument("-C", "--fetch-chunk-size", default=5000, type=int, help="Maximum number of assets to fetch with a single API call") parser.add_argument("-l", "--log-level", default="INFO", choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'], help="Log level to use") -parser.add_argument("-i", "--ignore-ssl", action="store_true", help="Set to true to ignore SSL verification") +parser.add_argument("-k", "--insecure", action="store_true", help="Set to true to ignore SSL verification") args = vars(parser.parse_args()) # set up logger to log in logfmt format logging.basicConfig(level=args["log_level"], stream=sys.stdout, format='time=%(asctime)s level=%(levelname)s msg=%(message)s') @@ -42,7 +42,7 @@ album_levels = args["album_levels"] # Album Levels Range handling album_levels_range_arr = () album_level_separator = args["album_separator"] -ignore_ssl = args["ignore_ssl"] +insecure = args["insecure"] logging.debug("root_path = %s", root_paths) logging.debug("root_url = %s", root_url) logging.debug("api_key = %s", api_key) @@ -52,14 +52,14 @@ logging.debug("unattended = %s", unattended) logging.debug("album_levels = %s", album_levels) #logging.debug("album_levels_range = %s", album_levels_range) logging.debug("album_level_separator = %s", album_level_separator) -logging.debug("ignore_ssl = %s", ignore_ssl) +logging.debug("insecure = %s", insecure) # Verify album levels if is_integer(album_levels) and album_levels == 0: parser.print_help() exit(1) -if ignore_ssl: +if insecure: urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # Verify album levels range @@ -101,7 +101,7 @@ requests_kwargs = { 'Content-Type': 'application/json', 'Accept': 'application/json' }, - 'verify' : not ignore_ssl + 'verify' : not insecure } # Yield successive n-sized From a75e5ac1f85ee797d26070e15b3d94ab4227e8ed Mon Sep 17 00:00:00 2001 From: Salvoxia Date: Tue, 30 Jul 2024 20:39:47 +0200 Subject: [PATCH 3/8] Added urllib3 to requirements.txt --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 663bd1f..345bc27 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -requests \ No newline at end of file +requests +urllib3 \ No newline at end of file From 8135b708f4cfce3fbae1d7a2c2962ea41506a169 Mon Sep 17 00:00:00 2001 From: Salvoxia Date: Tue, 30 Jul 2024 20:40:02 +0200 Subject: [PATCH 4/8] Added documentation for new option to skip SSL verification --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 872d811..7732eae 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ pip3 install -r requirements.txt 3. Run the script ``` python3 ./immich_auto_album.py -h -usage: immich_auto_album.py [-h] [-r ROOT_PATH] [-u] [-a ALBUM_LEVELS] [-s ALBUM_SEPARATOR] [-c CHUNK_SIZE] [-C FETCH_CHUNK_SIZE] [-l {CRITICAL,ERROR,WARNING,INFO,DEBUG}] root_path api_url api_key +usage: immich_auto_album.py [-h] [-r ROOT_PATH] [-u] [-a ALBUM_LEVELS] [-s ALBUM_SEPARATOR] [-c CHUNK_SIZE] [-C FETCH_CHUNK_SIZE] [-l {CRITICAL,ERROR,WARNING,INFO,DEBUG}] [-k] root_path api_url api_key Create Immich Albums from an external library path based on the top level folders @@ -44,8 +44,8 @@ options: Additional external libarary root path in Immich; May be specified multiple times for multiple import paths or external libraries. (default: None) -u, --unattended Do not ask for user confirmation after identifying albums. Set this flag to run script as a cronjob. (default: False) -a ALBUM_LEVELS, --album-levels ALBUM_LEVELS - Number of sub-folders or range of sub-folder levels below the root path used for album name creation. Positive numbers start from top of the folder structure, negative numbers from the bottom. Cannot be 0. If a range should be set, the start level and end level must be separated by a comma - like ','. If negative levels are used in a range, must be less than or equal to . (default: 1) + Number of sub-folders or range of sub-folder levels below the root path used for album name creation. Positive numbers start from top of the folder structure, negative numbers from the bottom. Cannot be 0. If a range should be set, the + start level and end level must be separated by a comma like ','. If negative levels are used in a range, must be less than or equal to . (default: 1) -s ALBUM_SEPARATOR, --album-separator ALBUM_SEPARATOR Separator string to use for compound album names created from nested folders. Only effective if -a is set to a value > 1 (default: ) -c CHUNK_SIZE, --chunk-size CHUNK_SIZE @@ -54,6 +54,7 @@ options: Maximum number of assets to fetch with a single API call (default: 5000) -l {CRITICAL,ERROR,WARNING,INFO,DEBUG}, --log-level {CRITICAL,ERROR,WARNING,INFO,DEBUG} Log level to use (default: INFO) + -k, --insecure Set to true to ignore SSL verification (default: False) ``` __Plain example without optional arguments:__ @@ -83,6 +84,7 @@ The environment variables are analoguous to the script's command line arguments. | CHUNK_SIZE | no | Maximum number of assets to add to an album with a single API call (default: 2000) | | FETCH_CHUNK_SIZE | no | Maximum number of assets to fetch with a single API call (default: 5000) | | LOG_LEVEL | no | Log level to use (default: INFO), allowed values: CRITICAL,ERROR,WARNING,INFO,DEBUG | +| INSECURE | no | Set to `true` to disable SSL verification for the Immich API server, useful for self-signed certificates (default: `false`), allowed values: `true`, `false` | #### Run the container with Docker From 7ea0ee835579c19d42541d091f207595c3a1501f Mon Sep 17 00:00:00 2001 From: Salvoxia Date: Tue, 30 Jul 2024 20:40:20 +0200 Subject: [PATCH 5/8] Docker Added new environment variable INSECURE to skip SSL verification --- docker/immich_auto_album.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docker/immich_auto_album.sh b/docker/immich_auto_album.sh index bde12b7..0f31a69 100644 --- a/docker/immich_auto_album.sh +++ b/docker/immich_auto_album.sh @@ -38,6 +38,10 @@ if [ ! -z "$LOG_LEVEL" ]; then args="-l $LOG_LEVEL $args" fi +if [ "$INSECURE" = "true" ]; then + args="-k $args" +fi + BASEDIR=$(dirname "$0") echo $args | xargs python3 -u $BASEDIR/immich_auto_album.py \ No newline at end of file From 94abaedb274ff4ba8d73468999b11ddd8b310183 Mon Sep 17 00:00:00 2001 From: Salvoxia Date: Tue, 30 Jul 2024 21:09:28 +0200 Subject: [PATCH 6/8] Added support for ignoring folders and files with --ignore --- immich_auto_album.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/immich_auto_album.py b/immich_auto_album.py index a375252..88b62a3 100644 --- a/immich_auto_album.py +++ b/immich_auto_album.py @@ -27,6 +27,7 @@ parser.add_argument("-c", "--chunk-size", default=2000, type=int, help="Maximum parser.add_argument("-C", "--fetch-chunk-size", default=5000, type=int, help="Maximum number of assets to fetch with a single API call") parser.add_argument("-l", "--log-level", default="INFO", choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'], help="Log level to use") parser.add_argument("-k", "--insecure", action="store_true", help="Set to true to ignore SSL verification") +parser.add_argument("-i", "--ignore", default="", type=str, help="A string containing a list of folders, sub-folder sequences or file names separated by ':' that will be ignored.") args = vars(parser.parse_args()) # set up logger to log in logfmt format logging.basicConfig(level=args["log_level"], stream=sys.stdout, format='time=%(asctime)s level=%(levelname)s msg=%(message)s') @@ -43,6 +44,7 @@ album_levels = args["album_levels"] album_levels_range_arr = () album_level_separator = args["album_separator"] insecure = args["insecure"] +ignore_albums = args["ignore"] logging.debug("root_path = %s", root_paths) logging.debug("root_url = %s", root_url) logging.debug("api_key = %s", api_key) @@ -53,6 +55,7 @@ logging.debug("album_levels = %s", album_levels) #logging.debug("album_levels_range = %s", album_levels_range) logging.debug("album_level_separator = %s", album_level_separator) logging.debug("insecure = %s", insecure) +logging.debug("ignore = %s", ignore_albums) # Verify album levels if is_integer(album_levels) and album_levels == 0: @@ -93,6 +96,10 @@ if not is_integer(album_levels): album_levels_range_arr[0] -= 1 album_levels_range_arr[1] -= 1 +if not ignore_albums == "": + ignore_albums = ignore_albums.split(":") +else: + ignore_albums = False # Request arguments for API calls requests_kwargs = { @@ -316,6 +323,17 @@ for asset in assets: for root_path in root_paths: if root_path not in asset_path: continue + # Check ignore_albums + ignore = False + if ignore_albums: + for ignore_entry in ignore_albums: + if ignore_entry in asset_path: + ignore = True + break + if ignore: + logging.debug("Ignoring asset %s due to ignore_albums setting!", asset_path) + continue + # Chunks of the asset's path below root_path path_chunks = asset_path.replace(root_path, '').split('/') # A single chunk means it's just the image file in no sub folder, ignore From 9602b6a7eaa03839f28c5eb8507d2e7debb4d40c Mon Sep 17 00:00:00 2001 From: Salvoxia Date: Tue, 30 Jul 2024 21:09:57 +0200 Subject: [PATCH 7/8] README Added documentation for new -i/--ignore option --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7732eae..ef7f5e4 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,7 @@ pip3 install -r requirements.txt ``` 3. Run the script ``` -python3 ./immich_auto_album.py -h -usage: immich_auto_album.py [-h] [-r ROOT_PATH] [-u] [-a ALBUM_LEVELS] [-s ALBUM_SEPARATOR] [-c CHUNK_SIZE] [-C FETCH_CHUNK_SIZE] [-l {CRITICAL,ERROR,WARNING,INFO,DEBUG}] [-k] root_path api_url api_key +usage: immich_auto_album.py [-h] [-r ROOT_PATH] [-u] [-a ALBUM_LEVELS] [-s ALBUM_SEPARATOR] [-c CHUNK_SIZE] [-C FETCH_CHUNK_SIZE] [-l {CRITICAL,ERROR,WARNING,INFO,DEBUG}] [-k] [-i IGNORE] root_path api_url api_key Create Immich Albums from an external library path based on the top level folders @@ -55,6 +54,8 @@ options: -l {CRITICAL,ERROR,WARNING,INFO,DEBUG}, --log-level {CRITICAL,ERROR,WARNING,INFO,DEBUG} Log level to use (default: INFO) -k, --insecure Set to true to ignore SSL verification (default: False) + -i IGNORE, --ignore IGNORE + A string containing a list of folders, sub-folder sequences or file names separated by ':' that will be ignored. (default: ) ``` __Plain example without optional arguments:__ @@ -85,6 +86,7 @@ The environment variables are analoguous to the script's command line arguments. | FETCH_CHUNK_SIZE | no | Maximum number of assets to fetch with a single API call (default: 5000) | | LOG_LEVEL | no | Log level to use (default: INFO), allowed values: CRITICAL,ERROR,WARNING,INFO,DEBUG | | INSECURE | no | Set to `true` to disable SSL verification for the Immich API server, useful for self-signed certificates (default: `false`), allowed values: `true`, `false` | +| INSECURE | no | A string containing a list of folders, sub-folder sequences or file names separated by ':' that will be ignored. | #### Run the container with Docker @@ -169,6 +171,11 @@ Albums created for `root_path = /external_libs/photos` (`--album-levels` is impl - `Birthdays` (containing all images from Birthdays itself as well as `John` and `Jane`) - `Skiing 2023` + Albums created for `root_path = /external_libs/photos` (`--album-levels` is implicitly set to `1`) and `--ignore "Vacation"`: + - `2020` (containing all images from `2020`, `2020/02 Feb` and `2020/08 Aug`, but __NOT__ `2020/02 Feb/Vacation` or `2020/08 Aug/Vacation`) + - `Birthdays` (containing all images from Birthdays itself as well as `John` and `Jane`) + - `Skiing 2023` + Albums created for `root_path = /external_libs/photos/Birthdays`: - `John` - `Jane` From 580c4f3c09e121c2b1ee968df6de089a347a3789 Mon Sep 17 00:00:00 2001 From: Salvoxia Date: Tue, 30 Jul 2024 21:11:17 +0200 Subject: [PATCH 8/8] Docker Added support for new IGNORE environment variable --- docker/immich_auto_album.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docker/immich_auto_album.sh b/docker/immich_auto_album.sh index 0f31a69..2fef497 100644 --- a/docker/immich_auto_album.sh +++ b/docker/immich_auto_album.sh @@ -42,6 +42,10 @@ if [ "$INSECURE" = "true" ]; then args="-k $args" fi +if [ ! -z "$IGNORE" ]; then + args="-i \"$IGNORE\" $args" +fi + BASEDIR=$(dirname "$0") echo $args | xargs python3 -u $BASEDIR/immich_auto_album.py \ No newline at end of file