Added option -m/--mode to either cleanup all albums created by the script or delete all albums for that user
This commit is contained in:
parent
870d34144c
commit
261f36065b
1 changed files with 68 additions and 3 deletions
|
@ -15,6 +15,15 @@ def is_integer(str):
|
|||
except ValueError:
|
||||
return False
|
||||
|
||||
# Constants holding script run modes
|
||||
# Creat albums based on folder names and script arguments
|
||||
SCRIPT_MODE_CREATE = "CREATE"
|
||||
# Create album names based on folder names, but delete these albums
|
||||
SCRIPT_MODE_CLEANUP = "CLEANUP"
|
||||
# Delete ALL albums
|
||||
SCRIPT_MODE_DELETE_ALL = "DELETE_ALL"
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="Create Immich Albums from an external library path based on the top level folders", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument("root_path", action='append', help="The external libarary's root path in Immich")
|
||||
parser.add_argument("api_url", help="The root API URL of immich, e.g. https://immich.mydomain.com/api/")
|
||||
|
@ -28,6 +37,7 @@ parser.add_argument("-C", "--fetch-chunk-size", default=5000, type=int, help="Ma
|
|||
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.")
|
||||
parser.add_argument("-m", "--mode", default=SCRIPT_MODE_CREATE, choices=[SCRIPT_MODE_CREATE, SCRIPT_MODE_CLEANUP, SCRIPT_MODE_DELETE_ALL], help="Mode for the script to run with. CREATE = Create albums based on folder names and provided arguments; CLEANUP = Create album nmaes based on current images and script arguments, but delete albums if they exist; DELETE_ALL = Delete all albums. If the mode is anything but CREATE, --unattended does not have any effect.")
|
||||
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')
|
||||
|
@ -45,6 +55,12 @@ album_levels_range_arr = ()
|
|||
album_level_separator = args["album_separator"]
|
||||
insecure = args["insecure"]
|
||||
ignore_albums = args["ignore"]
|
||||
mode = args["mode"]
|
||||
|
||||
# Override unattended if we're running in destructive mode
|
||||
if mode != SCRIPT_MODE_CREATE:
|
||||
unattended = False
|
||||
|
||||
logging.debug("root_path = %s", root_paths)
|
||||
logging.debug("root_url = %s", root_url)
|
||||
logging.debug("api_key = %s", api_key)
|
||||
|
@ -219,7 +235,11 @@ def fetchAssetsMinorV106():
|
|||
assets = []
|
||||
# prepare request body
|
||||
body = {}
|
||||
body['isNotInAlbum'] = 'true'
|
||||
# only request images that are not in any album if we are running in CREATE mode,
|
||||
# otherwise we need all images, even if they are part of an album
|
||||
if mode == SCRIPT_MODE_CREATE:
|
||||
body['isNotInAlbum'] = 'true'
|
||||
|
||||
# This API call allows a maximum page size of 1000
|
||||
number_of_assets_to_fetch_per_request_search = min(1000, number_of_assets_to_fetch_per_request)
|
||||
body['size'] = number_of_assets_to_fetch_per_request_search
|
||||
|
@ -246,7 +266,7 @@ def fetchAssetsMinorV106():
|
|||
return assets
|
||||
|
||||
|
||||
# Fetches assets from the Immich API
|
||||
# Fetches albums from the Immich API
|
||||
# Takes different API versions into account for compatibility
|
||||
def fetchAlbums():
|
||||
apiEndpoint = 'albums'
|
||||
|
@ -257,6 +277,20 @@ def fetchAlbums():
|
|||
r.raise_for_status()
|
||||
return r.json()
|
||||
|
||||
# Deletes an album identified by album['id']
|
||||
# Takes different API versions into account for compatibility
|
||||
# Returns False if the album could not be deleted, otherwise True
|
||||
def deleteAlbum(album):
|
||||
apiEndpoint = 'albums'
|
||||
if version['major'] == 1 and version['minor'] <= 105:
|
||||
apiEndpoint = 'album'
|
||||
logging.debug("Album ID = %s, Album Name = %s", album['id'], album['albumName'])
|
||||
r = requests.delete(root_url+apiEndpoint+'/'+album['id'], **requests_kwargs)
|
||||
if r.status_code not in [200, 201]:
|
||||
logging.error("Error deleting album %s: %s", album['albumName'], r.reason)
|
||||
return False
|
||||
return True
|
||||
|
||||
# Creates an album with the provided name and returns the ID of the
|
||||
# created album
|
||||
def createAlbum(albumName):
|
||||
|
@ -309,6 +343,19 @@ if root_url[-1] != '/':
|
|||
root_url = root_url + '/'
|
||||
|
||||
version = fetchServerVersion()
|
||||
# Special case: Run Mode DELETE_ALL albums
|
||||
if mode == SCRIPT_MODE_DELETE_ALL:
|
||||
albums = fetchAlbums()
|
||||
logging.info("%d existing albums identified", len(albums))
|
||||
print("Going to delete ALL albums! Press enter to proceed, Ctrl+C to abort")
|
||||
input()
|
||||
cpt = 0
|
||||
for album in albums:
|
||||
if deleteAlbum(album):
|
||||
logging.info("Deleted album %s", album['albumName'])
|
||||
cpt += 1
|
||||
logging.info("Deleted %d/%d albums", cpt, len(albums))
|
||||
exit(0)
|
||||
|
||||
logging.info("Requesting all assets")
|
||||
assets = fetchAssets()
|
||||
|
@ -353,7 +400,10 @@ album_to_assets = {k:v for k, v in sorted(album_to_assets.items(), key=(lambda i
|
|||
logging.info("%d albums identified", len(album_to_assets))
|
||||
logging.info("Album list: %s", list(album_to_assets.keys()))
|
||||
if not unattended:
|
||||
print("Press Enter to continue, Ctrl+C to abort")
|
||||
userHint = "Press enter to create these albums, Ctrl+C to abort"
|
||||
if mode != SCRIPT_MODE_CREATE:
|
||||
userHint = "Attention! Press enter to DELETE these albums (if they exist), Ctrl+C to abort"
|
||||
print(userHint)
|
||||
input()
|
||||
|
||||
|
||||
|
@ -365,7 +415,22 @@ albums = fetchAlbums()
|
|||
album_to_id = {album['albumName']:album['id'] for album in albums }
|
||||
logging.info("%d existing albums identified", len(albums))
|
||||
|
||||
# mode CLEANUP
|
||||
if mode == SCRIPT_MODE_CLEANUP:
|
||||
cpt = 0
|
||||
for album in album_to_assets:
|
||||
if album in album_to_id:
|
||||
album_to_delete = dict()
|
||||
album_to_delete['id'] = album_to_id[album]
|
||||
album_to_delete['albumName'] = album
|
||||
if deleteAlbum(album_to_delete):
|
||||
logging.info("Deleted album %s", album_to_delete['albumName'])
|
||||
cpt += 1
|
||||
logging.info("Deleted %d/%d albums", cpt, len(album_to_assets))
|
||||
exit(0)
|
||||
|
||||
|
||||
# mode CREATE
|
||||
logging.info("Creating albums if needed")
|
||||
cpt = 0
|
||||
for album in album_to_assets:
|
||||
|
|
Loading…
Reference in a new issue