Merge pull request #26 from Salvoxia/dev
Merge features from Dev branch
This commit is contained in:
commit
65c1d551e0
4 changed files with 50 additions and 6 deletions
17
README.md
17
README.md
|
@ -28,8 +28,7 @@ pip3 install -r requirements.txt
|
||||||
```
|
```
|
||||||
3. Run the script
|
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] [-i IGNORE] 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}] root_path api_url api_key
|
|
||||||
|
|
||||||
Create Immich Albums from an external library path based on the top level folders
|
Create Immich Albums from an external library path based on the top level folders
|
||||||
|
|
||||||
|
@ -44,8 +43,8 @@ options:
|
||||||
Additional external libarary root path in Immich; May be specified multiple times for multiple import paths or external libraries. (default: None)
|
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)
|
-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
|
-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
|
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
|
||||||
like '<startLevel>,<endLevel>'. If negative levels are used in a range, <startLevel> must be less than or equal to <endLevel>. (default: 1)
|
start level and end level must be separated by a comma like '<startLevel>,<endLevel>'. If negative levels are used in a range, <startLevel> must be less than or equal to <endLevel>. (default: 1)
|
||||||
-s ALBUM_SEPARATOR, --album-separator ALBUM_SEPARATOR
|
-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: )
|
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
|
-c CHUNK_SIZE, --chunk-size CHUNK_SIZE
|
||||||
|
@ -54,6 +53,9 @@ options:
|
||||||
Maximum number of assets to fetch with a single API call (default: 5000)
|
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}
|
-l {CRITICAL,ERROR,WARNING,INFO,DEBUG}, --log-level {CRITICAL,ERROR,WARNING,INFO,DEBUG}
|
||||||
Log level to use (default: INFO)
|
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:__
|
__Plain example without optional arguments:__
|
||||||
|
@ -83,6 +85,8 @@ 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) |
|
| 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) |
|
| 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 |
|
| 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
|
#### Run the container with Docker
|
||||||
|
|
||||||
|
@ -167,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`)
|
- `Birthdays` (containing all images from Birthdays itself as well as `John` and `Jane`)
|
||||||
- `Skiing 2023`
|
- `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`:
|
Albums created for `root_path = /external_libs/photos/Birthdays`:
|
||||||
- `John`
|
- `John`
|
||||||
- `Jane`
|
- `Jane`
|
||||||
|
|
|
@ -38,6 +38,14 @@ if [ ! -z "$LOG_LEVEL" ]; then
|
||||||
args="-l $LOG_LEVEL $args"
|
args="-l $LOG_LEVEL $args"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$INSECURE" = "true" ]; then
|
||||||
|
args="-k $args"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$IGNORE" ]; then
|
||||||
|
args="-i \"$IGNORE\" $args"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
BASEDIR=$(dirname "$0")
|
BASEDIR=$(dirname "$0")
|
||||||
echo $args | xargs python3 -u $BASEDIR/immich_auto_album.py
|
echo $args | xargs python3 -u $BASEDIR/immich_auto_album.py
|
|
@ -4,6 +4,7 @@ import logging
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
import urllib3
|
||||||
|
|
||||||
# Trying to deal with python's isnumeric() function
|
# Trying to deal with python's isnumeric() function
|
||||||
# not recognizing negative numbers
|
# not recognizing negative numbers
|
||||||
|
@ -25,6 +26,8 @@ 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", "--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("-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("-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())
|
args = vars(parser.parse_args())
|
||||||
# set up logger to log in logfmt format
|
# 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')
|
logging.basicConfig(level=args["log_level"], stream=sys.stdout, format='time=%(asctime)s level=%(levelname)s msg=%(message)s')
|
||||||
|
@ -40,6 +43,8 @@ album_levels = args["album_levels"]
|
||||||
# Album Levels Range handling
|
# Album Levels Range handling
|
||||||
album_levels_range_arr = ()
|
album_levels_range_arr = ()
|
||||||
album_level_separator = args["album_separator"]
|
album_level_separator = args["album_separator"]
|
||||||
|
insecure = args["insecure"]
|
||||||
|
ignore_albums = args["ignore"]
|
||||||
logging.debug("root_path = %s", root_paths)
|
logging.debug("root_path = %s", root_paths)
|
||||||
logging.debug("root_url = %s", root_url)
|
logging.debug("root_url = %s", root_url)
|
||||||
logging.debug("api_key = %s", api_key)
|
logging.debug("api_key = %s", api_key)
|
||||||
|
@ -49,12 +54,17 @@ logging.debug("unattended = %s", unattended)
|
||||||
logging.debug("album_levels = %s", album_levels)
|
logging.debug("album_levels = %s", album_levels)
|
||||||
#logging.debug("album_levels_range = %s", album_levels_range)
|
#logging.debug("album_levels_range = %s", album_levels_range)
|
||||||
logging.debug("album_level_separator = %s", album_level_separator)
|
logging.debug("album_level_separator = %s", album_level_separator)
|
||||||
|
logging.debug("insecure = %s", insecure)
|
||||||
|
logging.debug("ignore = %s", ignore_albums)
|
||||||
|
|
||||||
# Verify album levels
|
# Verify album levels
|
||||||
if is_integer(album_levels) and album_levels == 0:
|
if is_integer(album_levels) and album_levels == 0:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
if insecure:
|
||||||
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||||
|
|
||||||
# Verify album levels range
|
# Verify album levels range
|
||||||
if not is_integer(album_levels):
|
if not is_integer(album_levels):
|
||||||
album_levels_range_split = album_levels.split(",")
|
album_levels_range_split = album_levels.split(",")
|
||||||
|
@ -86,6 +96,10 @@ if not is_integer(album_levels):
|
||||||
album_levels_range_arr[0] -= 1
|
album_levels_range_arr[0] -= 1
|
||||||
album_levels_range_arr[1] -= 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
|
# Request arguments for API calls
|
||||||
requests_kwargs = {
|
requests_kwargs = {
|
||||||
|
@ -93,7 +107,8 @@ requests_kwargs = {
|
||||||
'x-api-key': api_key,
|
'x-api-key': api_key,
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
}
|
},
|
||||||
|
'verify' : not insecure
|
||||||
}
|
}
|
||||||
|
|
||||||
# Yield successive n-sized
|
# Yield successive n-sized
|
||||||
|
@ -308,6 +323,17 @@ for asset in assets:
|
||||||
for root_path in root_paths:
|
for root_path in root_paths:
|
||||||
if root_path not in asset_path:
|
if root_path not in asset_path:
|
||||||
continue
|
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
|
# Chunks of the asset's path below root_path
|
||||||
path_chunks = asset_path.replace(root_path, '').split('/')
|
path_chunks = asset_path.replace(root_path, '').split('/')
|
||||||
# A single chunk means it's just the image file in no sub folder, ignore
|
# A single chunk means it's just the image file in no sub folder, ignore
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
requests
|
requests
|
||||||
|
urllib3
|
Loading…
Reference in a new issue