#!/bin/bash DB=/var/lib/navidrome/navidrome.db medias=/music no_cover_flag=.no_cover cover_img=cover mbz_agent='getCover/0.1 (https://seb.lautre.net/git/seb/scripts)' test -e $0.conf && source $0.conf coverart=$(mktemp --dry-run /dev/shm/XXXXXXXX) sizes=(500 large small 250 1200) OK () { echo -e "\e[3;32m ${1:-OK} \e[0;m"; return 0; } WARNING () { echo -e "\e[3;33m ${1:-alerte} \e[0;m"; return 1; } ERROR () { echo -e "\e[3;31m ${1:-erreur} \e[0;m"; return 1; } sql_request () { sqlite3 $DB <<< "$1" } covered () { case "${forcing_level:-none}" in retry) if test -w "${album#*:}/$no_cover_flag"; then rm -f "${album#*:}/$no_cover_flag" 2>/dev/null return 1 else return 0 fi ;; force) rm -f "${album#*:}/$no_cover_flag" 2>/dev/null return 1 ;; none) if compgen -G "${album#*:}/$cover_img.*" > /dev/null; then return 0 elif test -e "${album#*:}/$no_cover_flag"; then return 0 else return 1 fi ;; esac } get_image () { install_image () { mv -f /dev/shm/$2 ${album#*:}/$cover_img.${2##*.} \ && OK \ || ERROR "échec en écriture" } if curl -Ls $1 > /dev/shm/$2; then mime_type=$(file -bn --mime-type /dev/shm/$2) if [[ ${mime_type:-erreur} =~ ^image/ ]]; then read -t 30 -p "${album%%:*} check ? " rc=$? if [[ "$rc$REPLY" =~ 0[OoYy] ]]; then display /dev/shm/$2 read -p "on garde ? " if [[ "$REPLY" =~ [OoYy] ]]; then install_image else rm /dev/shm/$2 WARNING "vignette rejetée" fi else install_image fi else WARNING "${album%%:*} type $mime_type" fi else ERROR "${album%%:*} échec du téléchargement" fi } get_from_mbz () { curl -Ls https://coverartarchive.org/release${1:+-group}/${album%%:*} > $coverart if test $(file -bn --mime-type $coverart) = application/json; then unset img for size in ${sizes[@]}; do img=$(jq -r '.images | .[] | select(.front == true) | .thumbnails | ."'$size'"?' $coverart 2>/dev/null) test "${img:-null}" != null && break done if test "${img:-null}" != null; then get_image "$img" "${album%%:*}.${img##*.}" fi else return 1 fi } mbz_api () { curl \ --request ${3:-GET} \ --user-agent "$mbz_agent" \ --silent \ --location \ --url "http://musicbrainz.org/ws/2/$1/?fmt=json&query=$2" sleep 2 } if ! test -d $medias; then ERROR "$medias n'est pas un répertoire" exit 1 fi if declare -f pre_get_cover > /dev/null; then pre_get_cover fi IFS=$'\n' for arg in $@; do if [[ $arg =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}:/ ]]; then from_CLI=1 albums[${#albums[@]}]="${arg%/}" elif [[ $arg =~ ^/ ]]; then from_CLI=1 albums[${#albums[@]}]=":${arg%/}" elif [[ $arg =~ / ]]; then from_CLI=1 albums[${#albums[@]}]=$(sql_request 'select mbz_album_id||":"||path from media_file where artist||"/"||album = "'$arg'"' \ | sed -r 's|/[^/]+*$||' \ | uniq \ | tail -1) elif [[ $arg =~ ^(force|retry)$ ]]; then forcing_level=$arg else WARNING "incohérence sur $arg" fi done if test -n "$from_CLI"; then forcing_level=force fi if test ${#albums[@]} -eq 0; then albums=($(sql_request 'select printf("%s:'${medias%/}'/%s/%s", mbz_album_id, artist, name) from album where cover_art_path = "" and name != "[Unknown Album]"')) fi for album in ${albums[@]}; do mbz_related=0 if ! test -d "${album#*:}"; then if test -n "$from_CLI"; then WARNING "${album#*:}: chemin inconnu" fi continue fi if covered; then continue fi echo "${album#*:}" if test -z "${album%%:*}"; then mbz_album_id=$(sql_request "select distinct mbz_album_id from media_file where path like '${album#*:}/%'") album=${mbz_album_id}${album} fi if test -n "${album%%:*}"; then mbz_related=1 if get_from_mbz; then continue else mbz_api release reid:${album%%:*} > $coverart rgid=$(jq --raw-output '.releases | .[] | ."release-group" .id // empty' $coverart) album="${rgid:-null}:${album#*:}" if get_from_mbz release-group; then continue fi if test -n "$rgid"; then mbz_api release-group rgid:$rgid > $coverart mbz_album_ids=($(jq --raw-output '."release-groups" | .[].releases | .[].id // empty' $coverart)) for reid in ${mbz_album_ids[@]}; do album=$reid:${album#*:} if get_from_mbz; then continue 2 fi done fi fi fi eval "$(sql_request 'select printf("artist=""%s"";album_name=""%s""", artist, name) from album where artist || "/" || name = "'${album#*:$medias/}'"')" eval $(php -r 'echo "_artist=".rawurlencode($argv[1]).";_album_name=".rawurlencode($argv[2]);' -- "$artist" "$album_name") mbz_api release "release:$_album_name%20AND%20artist:$_artist" > $coverart mbids=($(jq --raw-output --arg artist "${artist^^}" --arg album "${album_name^^}" ' .releases | .[] | select(.title | ascii_upcase == $album) | select(."artist-credit" | .[].name | ascii_upcase == $artist) | .id // empty' $coverart)) for mbid in ${mbids[@]}; do album="$mbid:${album#*:}" if get_from_mbz; then continue 2 fi done WARNING "pas trouvé ($(( ${mbz_related:-0} + ${#mbids[@]} )) relations sur musicbrainz)" touch "${album#*:}/$no_cover_flag" done rm -f $coverart if declare -f post_get_cover > /dev/null; then post_get_cover fi