scripts / get_cover /
248ae88 a year ago
1 contributor
221 lines | 6.637kb
#!/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