Skip to content

Instantly share code, notes, and snippets.

@daniele-athome
Last active May 1, 2024 16:38
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daniele-athome/82ce8af869ec0e20cd73b69acbc589bd to your computer and use it in GitHub Desktop.
Save daniele-athome/82ce8af869ec0e20cd73b69acbc589bd to your computer and use it in GitHub Desktop.
Synchronize library folder structure with immich albums
#!/usr/bin/env bash
# Synchronize library folder structure with immich albums
# Usage: ./sync-albums.sh http://immich-host:port/api <api-key> <library-path>
set -e
BASE_URL="$1"
API_KEY="$2"
LIBRARY_PATH="${3%/}/"
album_list=$(mktemp)
api_get() {
curl -s -X GET --location -H "X-api-key: $API_KEY" "$BASE_URL/$1"
}
_api_body() {
method="$1"
shift
curl -s -X "$method" --data-raw "$2" --location -H "content-type: application/json" -H "X-api-key: $API_KEY" "$BASE_URL/$1"
}
urlencode() {
jq -rn --arg data "$1" '$data|@uri'
}
api_post() {
_api_body "POST" "$@"
}
api_delete() {
_api_body "DELETE" "$@"
}
api_put() {
_api_body "PUT" "$@"
}
_ere_quote() {
# shellcheck disable=SC2016
# shellcheck disable=SC2001
sed 's/[][\.|$(){}?+*^]/\\&/g' <<< "$*"
}
get_album_id() {
grep -E '^.*\|'"$(_ere_quote "$1")"'$' "$album_list" | awk -F'|' '{print $1}'
}
echo "Requesting all albums..."
while read -r album; do
echo "$(echo "$album" | jq -r '.id')|$(echo "$album" | jq -r '.albumName')" >>"$album_list"
done < <(api_get album | jq -c '.[]')
echo "Requesting all albums assets..."
album_assets_dir="$(mktemp -d)"
while read -r album; do
album_id="$(echo "$album" | awk -F'|' '{print $1}')"
api_get "album/$(urlencode "$album_id")" | jq -r '.assets[].id' >"$album_assets_dir/$album_id"
done < "$album_list"
echo "Requesting all assets..."
while read -r asset; do
original_path="$(echo "$asset" | jq -r '.originalPath')"
album_name="$(dirname "${original_path#$LIBRARY_PATH}")"
# create album if it doesn't exist
album_id="$(get_album_id "$album_name")"
if [ "$album_id" == "" ]; then
echo "Creating album '$album_name'"
# shellcheck disable=SC2016
album_id="$(api_post album "$(jq -ncM --arg name "$album_name" '{"albumName":$name}')" | jq -r '.id')"
# add the newly created album to the list so it will be found later
echo "$album_id|$album_name" >>"$album_list"
fi
asset_id="$(echo "$asset" | jq -r '.id')"
# retrieve albums that contain the asset
# add this one (if not present), remove all the others
# this reflects a file system structure: a photo cannot belong to multiple albums
skip_add_to_album=
while read -r asset_album_id; do
if [ "$asset_album_id" != "$album_id" ]; then
# asset must always belong to one album only
api_delete "album/$(urlencode "$asset_album_id")/assets" "$(jq -ncM --arg id "$asset_id" '{"ids":[$id]}')" >/dev/null
else
# asset already belongs to album
skip_add_to_album=y
echo "Asset $asset_id already in album '$album_name'"
fi
done < <(grep -l "$asset_id" "$album_assets_dir"/* | xargs -r basename)
if [ "$skip_add_to_album" == "" ]; then
# TODO make a single call per album
echo "Adding asset $asset_id to album '$album_name'"
api_put "album/$(urlencode "$album_id")/assets" "$(jq -ncM --arg id "$asset_id" '{"ids":[$id]}')" >/dev/null
fi
done < <(api_get asset | jq -c '.[]')
@daniele-athome
Copy link
Author

Published in immich-app/immich#3382

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment