#!/usr/bin/env bash
scriptVersion = "1.0.3"
if [ -z " $lidarrUrl " ] || [ -z " $lidarrApiKey " ] ; then
lidarrUrlBase = " $( cat /config/config.xml | xq | jq -r .Config.UrlBase) "
if [ " $lidarrUrlBase " = = "null" ] ; then
lidarrUrlBase = ""
else
lidarrUrlBase = " / $( echo " $lidarrUrlBase " | sed "s/\///g" ) "
fi
lidarrApiKey = " $( cat /config/config.xml | xq | jq -r .Config.ApiKey) "
lidarrAgentInstanceId = " $( echo " $lidarrApiKey " | cut -c1-10) "
lidarrPort = " $( cat /config/config.xml | xq | jq -r .Config.Port) "
lidarrUrl = " http://localhost: ${ lidarrPort } ${ lidarrUrlBase } "
fi
agent = "lidarr-extended ( https://github.com/RandomNinjaAtk/docker-lidarr-extended )"
musicbrainzMirror = https://musicbrainz.org
musicbrainzSleep = 5
# Debugging settings
#addRelatedArtists="true"
#addDeezerTopArtists="true"
#addDeezerTopAlbumArtists="true"
#addDeezerTopTrackArtists="true"
#topLimit="3"
#addRelatedArtists="true"
#numberOfRelatedArtistsToAddPerArtist="1"
#lidarrSearchForMissing=false
touch "/config/logs/AutoArtistAdder.txt"
chmod 666 "/config/logs/AutoArtistAdder.txt"
exec & > >( tee -a "/config/logs/AutoArtistAdder.txt" )
sleepTimer = 0.5
log ( ) {
m_time = ` date "+%F %T" `
echo $m_time " :: AutoArtistAdder :: $scriptVersion :: " $1
}
NotifyWebhook ( ) {
if [ " $webHook " ]
then
content = " $1 : $2 "
curl -s -X POST " { $webHook } " -H 'Content-Type: application/json' -d '{"event":"' " $1 " '", "message":"' " $2 " '", "content":"' " $content " '"}'
fi
}
AddDeezerTopArtists ( ) {
getDeezerArtistsIds = $( curl -s " https://api.deezer.com/chart/0/artists?limit= $1 " | jq -r ".data[].id" )
getDeezerArtistsIdsCount = $( echo " $getDeezerArtistsIds " | wc -l)
getDeezerArtistsIds = ( $( echo " $getDeezerArtistsIds " ) )
sleep $sleepTimer
description = "Top Artists"
AddDeezerArtistToLidarr
}
AddDeezerTopAlbumArtists ( ) {
getDeezerArtistsIds = $( curl -s " https://api.deezer.com/chart/0/albums?limit= $1 " | jq -r ".data[].artist.id" )
getDeezerArtistsIdsCount = $( echo " $getDeezerArtistsIds " | wc -l)
getDeezerArtistsIds = ( $( echo " $getDeezerArtistsIds " ) )
sleep $sleepTimer
description = "Top Album Artists"
AddDeezerArtistToLidarr
}
AddDeezerTopTrackArtists ( ) {
getDeezerArtistsIds = $( curl -s " https://api.deezer.com/chart/0/tracks?limit= $1 " | jq -r ".data[].artist.id" )
getDeezerArtistsIdsCount = $( echo " $getDeezerArtistsIds " | wc -l)
getDeezerArtistsIds = ( $( echo " $getDeezerArtistsIds " ) )
sleep $sleepTimer
description = "Top Track Artists"
AddDeezerArtistToLidarr
}
AddDeezerArtistToLidarr ( ) {
lidarrArtistsData = " $( curl -s " $lidarrUrl /api/v1/artist?apikey= ${ lidarrApiKey } " ) "
lidarrArtistIds = " $( echo " ${ lidarrArtistsData } " | jq -r ".[].foreignArtistId" ) "
deezerArtistsUrl = $( echo " ${ lidarrArtistsData } " | jq -r ".[].links | .[] | select(.name==\"deezer\") | .url" )
deezerArtistIds = " $( echo " $deezerArtistsUrl " | grep -o '[[:digit:]]*' | sort -u) "
log " Finding $description ... "
log " $getDeezerArtistsIdsCount $description Found... "
for id in ${ !getDeezerArtistsIds[@] } ; do
currentprocess = $(( $id + 1 ))
deezerArtistId = " ${ getDeezerArtistsIds [ $id ] } "
deezerArtistName = " $( curl -s https://api.deezer.com/artist/$deezerArtistId | jq -r .name) "
sleep $sleepTimer
log " $currentprocess of $getDeezerArtistsIdsCount :: $deezerArtistName :: Searching Musicbrainz for Deezer artist id ( $deezerArtistId ) "
if echo " $deezerArtistIds " | grep " ^ ${ deezerArtistId } $" | read; then
log " $currentprocess of $getDeezerArtistsIdsCount :: $deezerArtistName :: $deezerArtistId already in Lidarr... "
continue
fi
query_data = $( curl -s -A " $agent " " https://musicbrainz.org/ws/2/url?query=url:%22https://www.deezer.com/artist/ ${ deezerArtistId } %22&fmt=json " )
count = $( echo " $query_data " | jq -r ".count" )
if [ " $count " = = "0" ] ; then
sleep $musicbrainzSleep
query_data = $( curl -s -A " $agent " " https://musicbrainz.org/ws/2/url?query=url:%22http://www.deezer.com/artist/ ${ deezerArtistId } %22&fmt=json " )
count = $( echo " $query_data " | jq -r ".count" )
sleep $musicbrainzSleep
fi
if [ " $count " = = "0" ] ; then
query_data = $( curl -s -A " $agent " " https://musicbrainz.org/ws/2/url?query=url:%22http://deezer.com/artist/ ${ deezerArtistId } %22&fmt=json " )
count = $( echo " $query_data " | jq -r ".count" )
sleep $musicbrainzSleep
fi
if [ " $count " = = "0" ] ; then
query_data = $( curl -s -A " $agent " " https://musicbrainz.org/ws/2/url?query=url:%22https://deezer.com/artist/ ${ deezerArtistId } %22&fmt=json " )
count = $( echo " $query_data " | jq -r ".count" )
fi
if [ " $count " != "0" ] ; then
musicbrainz_main_artist_id = $( echo " $query_data " | jq -r '.urls[]."relation-list"[].relations[].artist.id' | head -n 1)
sleep $musicbrainzSleep
artist_data = $( curl -s -A " $agent " " https://musicbrainz.org/ws/2/artist/ $musicbrainz_main_artist_id ?fmt=json " )
artist_sort_name = " $( echo " $artist_data " | jq -r '."sort-name"' ) "
artist_formed = " $( echo " $artist_data " | jq -r '."begin-area".name' ) "
artist_born = " $( echo " $artist_data " | jq -r '."life-span".begin' ) "
gender = " $( echo " $artist_data " | jq -r ".gender" ) "
matched_id = true
data = $( curl -s " $lidarrUrl /api/v1/search?term=lidarr%3A $musicbrainz_main_artist_id " -H " X-Api-Key: $lidarrApiKey " | jq -r ".[]" )
artistName = " $( echo " $data " | jq -r ".artist.artistName" ) "
foreignId = " $( echo " $data " | jq -r ".foreignId" ) "
importListExclusionData = $( curl -s " $lidarrUrl /api/v1/importlistexclusion " -H " X-Api-Key: $lidarrApiKey " | jq -r ".[].foreignId" )
if echo " $importListExclusionData " | grep " ^ ${ foreignId } $" | read; then
log " $currentprocess of $getDeezerArtistsIdsCount :: $deezerArtistName :: ERROR :: Artist is on import exclusion block list, skipping.... "
continue
fi
data = $( curl -s " $lidarrUrl /api/v1/rootFolder " -H " X-Api-Key: $lidarrApiKey " | jq -r ".[]" )
path = " $( echo " $data " | jq -r ".path" ) "
path = $( echo $path | cut -d' ' -f1)
qualityProfileId = " $( echo " $data " | jq -r ".defaultQualityProfileId" ) "
qualityProfileId = $( echo $qualityProfileId | cut -d' ' -f1)
metadataProfileId = " $( echo " $data " | jq -r ".defaultMetadataProfileId" ) "
metadataProfileId = $( echo $metadataProfileId | cut -d' ' -f1)
data = " {
\" artistName\" : \" $artistName \" ,
\" foreignArtistId\" : \" $foreignId \" ,
\" qualityProfileId\" : $qualityProfileId ,
\" metadataProfileId\" : $metadataProfileId ,
\" monitored\" :true,
\" monitor\" :\" all\" ,
\" rootFolderPath\" : \" $path \" ,
\" addOptions\" :{ \" searchForMissingAlbums\" :$lidarrSearchForMissing }
} "
if echo " $lidarrArtistIds " | grep " ^ ${ musicbrainz_main_artist_id } $" | read; then
log " $currentprocess of $getDeezerArtistsIdsCount :: $deezerArtistName :: Already in Lidarr ( $musicbrainz_main_artist_id ), skipping... "
continue
fi
log " $currentprocess of $getDeezerArtistsIdsCount :: $deezerArtistName :: Adding $artistName to Lidarr ( $musicbrainz_main_artist_id )... "
LidarrTaskStatusCheck
lidarrAddArtist = $( curl -s " $lidarrUrl /api/v1/artist " -X POST -H 'Content-Type: application/json' -H " X-Api-Key: $lidarrApiKey " --data-raw " $data " )
else
log " $currentprocess of $getDeezerArtistsIdsCount :: $deezerArtistName :: Artist not found in Musicbrainz, please add \"https://deezer.com/artist/ ${ deezerArtistId } \" to the correct artist on Musicbrainz "
NotifyWebhook "ArtistError" " Artist not found in Musicbrainz, please add <https://deezer.com/artist/ ${ deezerArtistId } > to the correct artist on Musicbrainz "
fi
LidarrTaskStatusCheck
done
}
AddDeezerRelatedArtists ( ) {
log "Begin adding Lidarr related Artists from Deezer..."
lidarrArtistsData = " $( curl -s " $lidarrUrl /api/v1/artist?apikey= ${ lidarrApiKey } " ) "
lidarrArtistTotal = $( echo " ${ lidarrArtistsData } " | jq -r '.[].sortName' | wc -l)
lidarrArtistList = ( $( echo " ${ lidarrArtistsData } " | jq -r ".[].foreignArtistId" ) )
lidarrArtistIds = " $( echo " ${ lidarrArtistsData } " | jq -r ".[].foreignArtistId" ) "
lidarrArtistLinkDeezerIds = " $( echo " ${ lidarrArtistsData } " | jq -r ".[] | .links[] | select(.name==\"deezer\") | .url" | grep -o '[[:digit:]]*' ) "
log " $lidarrArtistTotal Artists Found "
deezerArtistsUrl = $( echo " ${ lidarrArtistsData } " | jq -r ".[].links | .[] | select(.name==\"deezer\") | .url" )
deezerArtistIds = " $( echo " $deezerArtistsUrl " | grep -o '[[:digit:]]*' | sort -u) "
for id in ${ !lidarrArtistList[@] } ; do
artistNumber = $(( $id + 1 ))
musicbrainzId = " ${ lidarrArtistList [ $id ] } "
lidarrArtistData = $( echo " ${ lidarrArtistsData } " | jq -r " .[] | select(.foreignArtistId==\" ${ musicbrainzId } \") " )
lidarrArtistName = " $( echo " ${ lidarrArtistData } " | jq -r " .artistName" ) "
deezerArtistUrl = $( echo " ${ lidarrArtistData } " | jq -r ".links | .[] | select(.name==\"deezer\") | .url" )
deezerArtistIds = ( $( echo " $deezerArtistUrl " | grep -o '[[:digit:]]*' | sort -u) )
lidarrArtistMonitored = $( echo " ${ lidarrArtistData } " | jq -r ".monitored" )
log " $artistNumber of $lidarrArtistTotal :: $wantedAlbumListSource :: $lidarrArtistName :: Adding Related Artists... "
if [ " $lidarrArtistMonitored " = = "false" ] ; then
log " $artistNumber of $lidarrArtistTotal :: $wantedAlbumListSource :: $lidarrArtistName :: Artist is not monitored :: skipping... "
continue
fi
for dId in ${ !deezerArtistIds[@] } ; do
deezerArtistId = " ${ deezerArtistIds [ $dId ] } "
deezerRelatedArtistData = $( curl -sL --fail " https://api.deezer.com/artist/ $deezerArtistId /related?limit= $numberOfRelatedArtistsToAddPerArtist " | jq -r ".data | sort_by(.nb_fan) | reverse | .[]" )
sleep $sleepTimer
getDeezerArtistsIds = ( $( echo $deezerRelatedArtistData | jq -r .id) )
getDeezerArtistsIdsCount = $( echo $deezerRelatedArtistData | jq -r .id | wc -l)
description = " $lidarrArtistName Related Artists "
AddDeezerArtistToLidarr
done
done
}
LidarrTaskStatusCheck ( ) {
alerted = no
until false
do
taskCount = $( curl -s " $lidarrUrl /api/v1/command?apikey= ${ lidarrApiKey } " | jq -r .[ ] .status | grep -v completed | grep -v failed | wc -l)
if [ " $taskCount " -ge "1" ] ; then
if [ " $alerted " = = "no" ] ; then
alerted = yes
log "STATUS :: LIDARR BUSY :: Pausing/waiting for all active Lidarr tasks to end..."
fi
sleep $musicbrainzSleep
else
break
fi
done
}
AddTidalRelatedArtists ( ) {
log "Begin adding Lidarr related Artists from Tidal..."
lidarrArtistsData = " $( curl -s " $lidarrUrl /api/v1/artist?apikey= ${ lidarrApiKey } " ) "
lidarrArtistTotal = $( echo " ${ lidarrArtistsData } " | jq -r '.[].sortName' | wc -l)
lidarrArtistList = ( $( echo " ${ lidarrArtistsData } " | jq -r ".[].foreignArtistId" ) )
lidarrArtistIds = " $( echo " ${ lidarrArtistsData } " | jq -r ".[].foreignArtistId" ) "
lidarrArtistLinkTidalIds = " $( echo " ${ lidarrArtistsData } " | jq -r ".[] | .links[] | select(.name==\"tidal\") | .url" | grep -o '[[:digit:]]*' | sort -u) "
log " $lidarrArtistTotal Artists Found "
for id in ${ !lidarrArtistList[@] } ; do
artistNumber = $(( $id + 1 ))
musicbrainzId = " ${ lidarrArtistList [ $id ] } "
lidarrArtistData = $( echo " ${ lidarrArtistsData } " | jq -r " .[] | select(.foreignArtistId==\" ${ musicbrainzId } \") " )
lidarrArtistName = " $( echo " ${ lidarrArtistData } " | jq -r " .artistName" ) "
serviceArtistUrl = $( echo " ${ lidarrArtistData } " | jq -r ".links | .[] | select(.name==\"tidal\") | .url" )
serviceArtistIds = ( $( echo " $serviceArtistUrl " | grep -o '[[:digit:]]*' | sort -u) )
lidarrArtistMonitored = $( echo " ${ lidarrArtistData } " | jq -r ".monitored" )
log " $artistNumber of $lidarrArtistTotal :: $lidarrArtistName :: Adding Related Artists... "
if [ " $lidarrArtistMonitored " = = "false" ] ; then
log " $artistNumber of $lidarrArtistTotal :: $lidarrArtistName :: Artist is not monitored :: skipping... "
continue
fi
for Id in ${ !serviceArtistIds[@] } ; do
serviceArtistId = " ${ serviceArtistIds [ $Id ] } "
serviceRelatedArtistData = $( curl -sL --fail " https://api.tidal.com/v1/pages/single-module-page/ae223310-a4c2-4568-a770-ffef70344441/4/b4b95795-778b-49c5-a34f-59aac055b662/1?artistId= $serviceArtistId &countryCode= $tidalCountryCode &deviceType=BROWSER " -H 'x-tidal-token: CzET4vdadNUFQ5JU' | jq -r .rows[ ] .modules[ ] .pagedList.items[ ] )
sleep $sleepTimer
serviceRelatedArtistsIds = ( $( echo $serviceRelatedArtistData | jq -r .id) )
serviceRelatedArtistsIdsCount = $( echo $serviceRelatedArtistData | jq -r .id | wc -l)
log " $artistNumber of $lidarrArtistTotal :: $lidarrArtistName :: $serviceArtistId :: Found $serviceRelatedArtistsIdsCount Artists, adding $numberOfRelatedArtistsToAddPerArtist ... "
AddTidalArtistToLidarr
done
done
}
AddTidalArtistToLidarr ( ) {
currentprocess = 0
for id in ${ !serviceRelatedArtistsIds[@] } ; do
currentprocess = $(( $id + 1 ))
if [ $currentprocess -gt $numberOfRelatedArtistsToAddPerArtist ] ; then
break
fi
serviceArtistId = " ${ serviceRelatedArtistsIds [ $id ] } "
serviceArtistName = " $( echo " $serviceRelatedArtistData " | jq -r " select(.id== $serviceArtistId ) | .name " ) "
log " $artistNumber of $lidarrArtistTotal :: $lidarrArtistName :: $currentprocess of $numberOfRelatedArtistsToAddPerArtist :: $serviceArtistName :: Searching Musicbrainz for Tidal artist id ( $serviceArtistId ) "
if echo " $lidarrArtistLinkTidalIds " | grep " ^ ${ serviceArtistId } $" | read; then
log " $artistNumber of $lidarrArtistTotal :: $lidarrArtistName :: $currentprocess of $numberOfRelatedArtistsToAddPerArtist :: $serviceArtistName :: $serviceArtistId already in Lidarr... "
continue
fi
query_data = $( curl -s -A " $agent " " https://musicbrainz.org/ws/2/url?query=url:%22https://listen.tidal.com/artist/ ${ serviceArtistId } %22&fmt=json " )
count = $( echo " $query_data " | jq -r ".count" )
if [ " $count " = = "0" ] ; then
sleep $musicbrainzSleep
query_data = $( curl -s -A " $agent " " https://musicbrainz.org/ws/2/url?query=url:%22http://listen.tidal.com/artist/ ${ serviceArtistId } %22&fmt=json " )
count = $( echo " $query_data " | jq -r ".count" )
fi
if [ " $count " = = "0" ] ; then
sleep $musicbrainzSleep
query_data = $( curl -s -A " $agent " " https://musicbrainz.org/ws/2/url?query=url:%22https://tidal.com/artist/ ${ serviceArtistId } %22&fmt=json " )
count = $( echo " $query_data " | jq -r ".count" )
fi
if [ " $count " = = "0" ] ; then
sleep $musicbrainzSleep
query_data = $( curl -s -A " $agent " " https://musicbrainz.org/ws/2/url?query=url:%22http://tidal.com/artist/ ${ serviceArtistId } %22&fmt=json " )
count = $( echo " $query_data " | jq -r ".count" )
fi
if [ " $count " != "0" ] ; then
musicbrainz_main_artist_id = $( echo " $query_data " | jq -r '.urls[]."relation-list"[].relations[].artist.id' | head -n 1)
data = $( curl -s " $lidarrUrl /api/v1/search?term=lidarr%3A $musicbrainz_main_artist_id " -H " X-Api-Key: $lidarrApiKey " | jq -r ".[]" )
artistName = " $( echo " $data " | jq -r ".artist.artistName" ) "
foreignId = " $( echo " $data " | jq -r ".foreignId" ) "
importListExclusionData = $( curl -s " $lidarrUrl /api/v1/importlistexclusion " -H " X-Api-Key: $lidarrApiKey " | jq -r ".[].foreignId" )
if echo " $importListExclusionData " | grep " ^ ${ foreignId } $" | read; then
log " $artistNumber of $lidarrArtistTotal :: $lidarrArtistName :: $currentprocess of $numberOfRelatedArtistsToAddPerArtist :: $serviceArtistName :: ERROR :: Artist is on import exclusion block list, skipping.... "
continue
fi
data = $( curl -s " $lidarrUrl /api/v1/rootFolder " -H " X-Api-Key: $lidarrApiKey " | jq -r ".[]" )
path = " $( echo " $data " | jq -r ".path" ) "
path = $( echo $path | cut -d' ' -f1)
qualityProfileId = " $( echo " $data " | jq -r ".defaultQualityProfileId" ) "
qualityProfileId = $( echo $qualityProfileId | cut -d' ' -f1)
metadataProfileId = " $( echo " $data " | jq -r ".defaultMetadataProfileId" ) "
metadataProfileId = $( echo $metadataProfileId | cut -d' ' -f1)
data = " {
\" artistName\" : \" $artistName \" ,
\" foreignArtistId\" : \" $foreignId \" ,
\" qualityProfileId\" : $qualityProfileId ,
\" metadataProfileId\" : $metadataProfileId ,
\" monitored\" :true,
\" monitor\" :\" all\" ,
\" rootFolderPath\" : \" $path \" ,
\" addOptions\" :{ \" searchForMissingAlbums\" :$lidarrSearchForMissing }
} "
if echo " $lidarrArtistIds " | grep " ^ ${ musicbrainz_main_artist_id } $" | read; then
log " $artistNumber of $lidarrArtistTotal :: $lidarrArtistName :: $currentprocess of $numberOfRelatedArtistsToAddPerArtist :: $serviceArtistName :: Already in Lidarr ( $musicbrainz_main_artist_id ), skipping... "
continue
fi
log " $artistNumber of $lidarrArtistTotal :: $lidarrArtistName :: $currentprocess of $numberOfRelatedArtistsToAddPerArtist :: $serviceArtistName :: Adding $artistName to Lidarr ( $musicbrainz_main_artist_id )... "
LidarrTaskStatusCheck
lidarrAddArtist = $( curl -s " $lidarrUrl /api/v1/artist " -X POST -H 'Content-Type: application/json' -H " X-Api-Key: $lidarrApiKey " --data-raw " $data " )
else
log " $artistNumber of $lidarrArtistTotal :: $lidarrArtistName :: $currentprocess of $numberOfRelatedArtistsToAddPerArtist :: $serviceArtistName :: ERROR :: Artist not found in Musicbrainz, please add \"https://listen.tidal.com/artist/ ${ serviceArtistId } \" to the correct artist on Musicbrainz "
NotifyWebhook "ArtistError" " Artist not found in Musicbrainz, please add <https://listen.tidal.com/artist/ ${ serviceArtistId } > to the correct artist on Musicbrainz "
fi
LidarrTaskStatusCheck
done
}
if [ -z $lidarrSearchForMissing ] ; then
lidarrSearchForMissing = true
fi
if [ " $addDeezerTopArtists " = = "true" ] ; then
AddDeezerTopArtists " $topLimit "
fi
if [ " $addDeezerTopAlbumArtists " = = "true" ] ; then
AddDeezerTopAlbumArtists " $topLimit "
fi
if [ " $addDeezerTopTrackArtists " = = "true" ] ; then
AddDeezerTopTrackArtists " $topLimit "
fi
if [ " $addRelatedArtists " = = "true" ] ; then
AddDeezerRelatedArtists
AddTidalRelatedArtists
fi
exit