2023-07-13 21:59:42 +02:00
#!/usr/bin/with-contenv bash
2024-11-26 22:01:19 +01:00
set -euo pipefail
while [ [ $# -gt 0 ] ] ; do
case $1 in
--state-dir)
STATE_DIR = " $2 "
shift
shift
; ;
*)
echo " Unknown option $1 "
exit 1
; ;
esac
done
2023-07-12 16:01:00 +02:00
scriptName = "Audio"
2023-07-20 12:58:49 +02:00
### Import Settings
2024-11-26 22:01:19 +01:00
# shellcheck source=../config/extended.conf
source " ${ STATE_DIR } /extended.conf "
2023-07-20 12:58:49 +02:00
#### Import Functions
2024-11-26 22:01:19 +01:00
source ../universal/functions.bash
2023-07-19 16:41:16 +02:00
2024-04-12 02:19:04 +02:00
AddTag ( ) {
log "adding arr-extended tag"
2024-11-26 22:01:19 +01:00
lidarrProcessIt = $( curl -s " $arrUrl /api/v1/tag " --header "X-Api-Key:" " ${ arrApiKey } " -H "Content-Type: application/json" --data-raw '{"label":"arr-extended"}' )
2024-04-12 02:19:04 +02:00
}
2024-04-06 22:12:21 +02:00
AddDownloadClient ( ) {
2024-11-26 22:01:19 +01:00
downloadClientsData = $( curl -s " $arrUrl /api/v1/downloadclient " --header "X-Api-Key:" " ${ arrApiKey } " -H "Content-Type: application/json" )
downloadClientCheck = " $( echo " $downloadClientsData " | grep "Arr-Extended" ) "
2024-04-13 02:54:03 +02:00
if [ -z " $downloadClientCheck " ] ; then
AddTag
if [ ! -d " $importPath " ] ; then
mkdir -p " $importPath "
fi
2024-04-30 01:48:51 +02:00
log "Adding download Client"
2024-11-26 22:01:19 +01:00
lidarrProcessIt = $( curl -s " $arrUrl /api/v1/downloadclient " --header "X-Api-Key:" " ${ arrApiKey } " -H "Content-Type: application/json" --data-raw " {\"enable\":true,\"protocol\":\"usenet\",\"priority\":10,\"removeCompletedDownloads\":true,\"removeFailedDownloads\":true,\"name\":\"Arr-Extended\",\"fields\":[{\"name\":\"nzbFolder\",\"value\":\" $importPath \"},{\"name\":\"watchFolder\",\"value\":\" $importPath \"}],\"implementationName\":\"Usenet Blackhole\",\"implementation\":\"UsenetBlackhole\",\"configContract\":\"UsenetBlackholeSettings\",\"infoLink\":\"https://wiki.servarr.com/lidarr/supported#usenetblackhole\",\"tags\":[]} " )
2024-04-13 02:54:03 +02:00
fi
2024-04-06 22:12:21 +02:00
}
verifyConfig ( ) {
2024-08-08 14:58:00 +02:00
### Import Settings
2024-11-26 22:01:19 +01:00
# shellcheck source=../config/extended.conf
source " ${ STATE_DIR } /extended.conf "
2023-07-15 16:22:25 +02:00
if [ " $enableAudio " != "true" ] ; then
log "Script is not enabled, enable by setting enableAudio to \"true\" by modifying the \"/config/extended.conf\" config file..."
2024-11-26 22:01:19 +01:00
exit 0
2023-07-15 16:22:25 +02:00
fi
if [ -z " $audioScriptInterval " ] ; then
audioScriptInterval = "15m"
fi
2023-07-11 14:14:37 +02:00
2023-07-15 16:22:25 +02:00
if [ -z " $downloadPath " ] ; then
2024-11-26 22:01:19 +01:00
downloadPath = " ${ STATE_DIR } /extended/downloads "
2023-07-15 16:22:25 +02:00
fi
2023-07-15 22:26:48 +02:00
2024-04-06 22:12:21 +02:00
if [ -z " $importPath " ] ; then
2024-11-26 22:01:19 +01:00
importPath = " ${ STATE_DIR } /extended/import "
2024-04-06 22:12:21 +02:00
fi
2023-07-28 11:47:18 +02:00
if [ -z " $failedDownloadAttemptThreshold " ] ; then
failedDownloadAttemptThreshold = "6"
fi
2023-07-28 12:18:42 +02:00
if [ -z " $tidalClientTestDownloadId " ] ; then
tidalClientTestDownloadId = "166356219"
fi
if [ -z " $deezerClientTestDownloadId " ] ; then
deezerClientTestDownloadId = "197472472"
fi
2024-01-11 19:32:47 +01:00
if [ -z " $ignoreInstrumentalRelease " ] ; then
2024-01-11 21:15:36 +01:00
ignoreInstrumentalRelease = "true"
2024-01-11 19:32:47 +01:00
fi
2024-04-05 02:12:55 +02:00
if [ -z " $downloadClientTimeOut " ] ; then
downloadClientTimeOut = "10m" # if not set, set to 10 minutes
fi
2024-08-01 15:36:02 +02:00
if [ -z " $preferSpecialEditions " ] ; then
preferSpecialEditions = "true"
fi
2024-04-05 02:12:55 +02:00
2023-07-15 22:26:48 +02:00
audioPath = " $downloadPath /audio "
2023-07-28 12:18:42 +02:00
2024-04-30 01:48:51 +02:00
2023-07-15 16:22:25 +02:00
}
2023-07-11 14:14:37 +02:00
Configuration ( ) {
2023-07-15 16:22:25 +02:00
sleepTimer = 0.5
tidaldlFail = 0
deemixFail = 0
sleep 5
2024-11-26 22:01:19 +01:00
if [ ! -d " ${ STATE_DIR } /xdg " ] ; then
mkdir -p " ${ STATE_DIR } /xdg "
2023-07-15 16:22:25 +02:00
fi
2023-07-18 15:51:54 +02:00
2024-11-26 22:01:19 +01:00
if [ -z " $topLimit " ] ; then
2023-07-11 14:14:37 +02:00
topLimit = 10
fi
verifyApiAccess
2024-04-30 01:48:51 +02:00
AddDownloadClient
2023-07-11 14:14:37 +02:00
if [ " $addDeezerTopArtists " = = "true" ] ; then
log " Add Deezer Top $topLimit Artists is enabled "
else
log "Add Deezer Top Artists is disabled (enable by setting addDeezerTopArtists=true)"
fi
2024-08-02 00:17:36 +02:00
2023-07-11 14:14:37 +02:00
if [ " $addDeezerTopAlbumArtists " = = "true" ] ; then
log " Add Deezer Top $topLimit Album Artists is enabled "
else
log "Add Deezer Top Album Artists is disabled (enable by setting addDeezerTopAlbumArtists=true)"
fi
if [ " $addDeezerTopTrackArtists " = = "true" ] ; then
log " Add Deezer Top $topLimit Track Artists is enabled "
else
log "Add Deezer Top Track Artists is disabled (enable by setting addDeezerTopTrackArtists=true)"
fi
if [ " $addRelatedArtists " = = "true" ] ; then
log "Add Deezer Related Artists is enabled"
log " Add $numberOfRelatedArtistsToAddPerArtist Deezer related Artist for each Lidarr Artist "
else
log "Add Deezer Related Artists is disabled (enable by setting addRelatedArtists=true)"
fi
2023-07-15 22:26:48 +02:00
log " Download Location: $audioPath "
2023-07-11 14:14:37 +02:00
log " Output format: $audioFormat "
if [ " $audioFormat " != "native" ] ; then
if [ " $audioFormat " = = "alac" ] ; then
audioBitrateText = "LOSSLESS"
else
audioBitrateText = " ${ audioBitrate } k "
fi
2023-07-18 15:51:54 +02:00
else
audioBitrateText = " $audioBitrate "
fi
2023-07-11 14:14:37 +02:00
log " Output bitrate: $audioBitrateText "
if [ " $requireQuality " = = "true" ] ; then
log "Download Quality Check Enabled"
else
log "Download Quality Check Disabled (enable by setting: requireQuality=true"
fi
if [ " $audioLyricType " = = "both" ] || [ " $audioLyricType " = = "explicit" ] || [ " $audioLyricType " = = "explicit" ] ; then
log " Preferred audio lyric type: $audioLyricType "
fi
log " Tidal Country Code set to: $tidalCountryCode "
if [ " $enableReplaygainTags " = = "true" ] ; then
log "Replaygain Tagging Enabled"
else
log "Replaygain Tagging Disabled"
fi
log " Match Distance: $matchDistance "
if [ $enableBeetsTagging = true ] ; then
log "Beets Tagging Enabled"
log " Beets Matching Threshold ${ beetsMatchPercentage } % "
2024-11-26 22:01:19 +01:00
beetsMatchPercentage = $(( 100 - beetsMatchPercentage ))
if grep "strong_rec_thresh: 0.04" " ${ STATE_DIR } /extended/beets-config.yaml " | read -r; then
2023-07-11 14:14:37 +02:00
log "Configuring Beets Matching Threshold"
2024-11-26 22:01:19 +01:00
sed -i " s/strong_rec_thresh: 0.04/strong_rec_thresh: 0. ${ beetsMatchPercentage } /g " " ${ STATE_DIR } /extended/beets-config.yaml "
2023-07-11 14:14:37 +02:00
fi
else
log "Beets Tagging Disabled"
fi
2023-07-28 11:47:18 +02:00
2024-08-01 15:36:02 +02:00
if [ " $preferSpecialEditions " = = "true" ] ; then
log "Prefer Special Editions Enabled"
else
log "Prefer Special Editions Disabled"
fi
2024-05-31 19:53:05 +02:00
log " Failed Download Attempt Threshold: $failedDownloadAttemptThreshold "
2023-07-11 14:14:37 +02:00
}
DownloadClientFreyr ( ) {
2024-11-26 22:01:19 +01:00
timeout $downloadClientTimeOut freyr --no-bar --no-net-check -d " $audioPath /incomplete " " deezer:album: $1 " 2>& 1
2023-07-11 14:14:37 +02:00
}
DownloadFormat ( ) {
if [ " $audioFormat " = = "native" ] ; then
if [ " $audioBitrate " = = "master" ] ; then
tidalQuality = Master
deemixQuality = flac
elif [ " $audioBitrate " = = "lossless" ] ; then
tidalQuality = HiFi
deemixQuality = flac
elif [ " $audioBitrate " = = "high" ] ; then
tidalQuality = High
deemixQuality = 320
elif [ " $audioBitrate " = = "low" ] ; then
tidalQuality = 128
deemixQuality = 128
else
log "ERROR :: Invalid audioFormat and audioBitrate options set..."
log "ERROR :: Change audioBitrate to a low, high, or lossless..."
log "ERROR :: Exiting..."
NotifyWebhook "FatalError" "Invalid audioFormat and audioBitrate options set"
2024-11-26 22:01:19 +01:00
exit 1
2023-07-11 14:14:37 +02:00
fi
else
bitrateError = "false"
audioFormatError = "false"
tidalQuality = HiFi
deemixQuality = flac
case " $audioBitrate " in
lossless | high | low)
bitrateError = "true"
; ;
*)
bitrateError = "false"
; ;
esac
if [ " $bitrateError " = = "true" ] ; then
log "ERROR :: Invalid audioBitrate options set..."
log "ERROR :: Change audioBitrate to a desired bitrate number, example: 192..."
log "ERROR :: Exiting..."
NotifyWebhook "FatalError" "audioBitrate options set"
2024-11-26 22:01:19 +01:00
exit 1
2023-07-11 14:14:37 +02:00
fi
case " $audioFormat " in
mp3 | alac | opus | aac)
audioFormatError = "false"
; ;
*)
audioFormatError = "true"
; ;
esac
if [ " $audioFormatError " = = "true" ] ; then
log "ERROR :: Invalid audioFormat options set..."
log "ERROR :: Change audioFormat to a desired format (opus or mp3 or aac or alac)"
NotifyWebhook "FatalError" "audioFormat options set"
2024-04-28 05:28:26 +02:00
log " Script sleeping for $audioScriptInterval ... "
sleep $audioScriptInterval
2023-07-11 14:14:37 +02:00
exit
fi
tidal-dl -q HiFi
deemixQuality = flac
bitrateError = ""
audioFormatError = ""
fi
}
DownloadFolderCleaner ( ) {
# check for completed download folder
2023-07-15 22:26:48 +02:00
if [ -d " $audioPath /complete " ] ; then
2023-07-11 14:14:37 +02:00
log "Removing prevously completed downloads that failed to import..."
# check for completed downloads older than 1 day
2024-11-26 22:01:19 +01:00
if find " $audioPath /complete " -mindepth 1 -type d -mtime +1 | read -r; then
2023-07-11 14:14:37 +02:00
# delete completed downloads older than 1 day, these most likely failed to import due to Lidarr failing to match
2024-11-26 22:01:19 +01:00
find " $audioPath /complete " -mindepth 1 -type d -mtime +1 -exec rm -rf "{}" \; & >/dev/null
2023-07-11 14:14:37 +02:00
fi
fi
}
TidalClientSetup ( ) {
log "TIDAL :: Verifying tidal-dl configuration"
2024-11-26 22:01:19 +01:00
touch " ${ STATE_DIR } /xdg/.tidal-dl.log "
if [ -f " ${ STATE_DIR } /xdg/.tidal-dl.json " ] ; then
rm " ${ STATE_DIR } /xdg/.tidal-dl.json "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
if [ ! -f " ${ STATE_DIR } /xdg/.tidal-dl.json " ] ; then
2023-07-11 14:14:37 +02:00
log "TIDAL :: No default config found, importing default config \"tidal.json\""
2024-11-26 22:01:19 +01:00
if [ -f " ${ STATE_DIR } /extended/tidal-dl.json " ] ; then
cp " ${ STATE_DIR } /extended/tidal-dl.json " " ${ STATE_DIR } /xdg/.tidal-dl.json "
2023-07-11 14:14:37 +02:00
fi
fi
TidaldlStatusCheck
2024-11-26 22:01:19 +01:00
tidal-dl -o " $audioPath /incomplete " 2>& 1
2023-07-11 14:14:37 +02:00
DownloadFormat
2024-11-26 22:01:19 +01:00
if [ ! -f " ${ STATE_DIR } /xdg/.tidal-dl.token.json " ] ; then
2023-07-11 14:14:37 +02:00
TidaldlStatusCheck
#log "TIDAL :: ERROR :: Downgrade tidal-dl for workaround..."
#pip3 install tidal-dl==2022.3.4.2 --no-cache-dir &>/dev/null
log "TIDAL :: ERROR :: Loading client for required authentication, please authenticate, then exit the client..."
NotifyWebhook "FatalError" "TIDAL requires authentication, please authenticate now (check logs)"
TidaldlStatusCheck
tidal-dl
fi
2024-11-26 22:01:19 +01:00
if [ ! -d " ${ STATE_DIR } /extended/cache/tidal " ] ; then
mkdir -p " ${ STATE_DIR } /extended/cache/tidal "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
if [ -d " ${ STATE_DIR } /extended/cache/tidal " ] ; then
2023-07-11 14:14:37 +02:00
log "TIDAL :: Purging album list cache..."
2024-11-26 22:01:19 +01:00
rm " ${ STATE_DIR } /extended/cache/tidal/*-albums.json " & >/dev/null
2023-07-11 14:14:37 +02:00
fi
2023-07-15 22:26:48 +02:00
if [ ! -d " $audioPath /incomplete " ] ; then
mkdir -p " $audioPath " /incomplete
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
rm -rf " $audioPath /incomplete/* "
2023-07-11 14:14:37 +02:00
fi
TidaldlStatusCheck
#log "TIDAL :: Upgrade tidal-dl to newer version..."
#pip3 install tidal-dl==2022.07.06.1 --no-cache-dir &>/dev/null
}
TidaldlStatusCheck ( ) {
2024-11-26 22:01:19 +01:00
until false; do
running = no
if pgrep -f "tidal-dl" | read -r; then
running = yes
log "STATUS :: TIDAL-DL :: BUSY :: Pausing/waiting for all active tidal-dl tasks to end..."
sleep 2
continue
fi
break
2023-07-11 14:14:37 +02:00
done
}
2023-07-28 12:18:42 +02:00
TidalClientTest ( ) {
log "TIDAL :: tidal-dl client setup verification..."
i = 0
while [ $i -lt 3 ] ; do
2024-11-26 22:01:19 +01:00
i = $(( i + 1 ))
2023-07-28 12:18:42 +02:00
TidaldlStatusCheck
2024-11-26 22:01:19 +01:00
tidal-dl -q Normal -o " $audioPath /incomplete " -l " $tidalClientTestDownloadId " 2>& 1
downloadCount = $( find " $audioPath /incomplete " -type f -regex ".*/.*\.\(flac\|opus\|m4a\|mp3\)" | wc -l)
if [ " $downloadCount " -le 0 ] ; then
2023-07-28 12:18:42 +02:00
continue
else
break
fi
done
tidalClientTest = "unknown"
2024-11-26 22:01:19 +01:00
if [ " $downloadCount " -le 0 ] ; then
if [ -f " ${ STATE_DIR } /xdg/.tidal-dl.token.json " ] ; then
rm " ${ STATE_DIR } /xdg/.tidal-dl.token.json "
2023-07-28 12:18:42 +02:00
fi
log "TIDAL :: ERROR :: Download failed"
log "TIDAL :: ERROR :: You will need to re-authenticate on next script run..."
log "TIDAL :: ERROR :: Exiting..."
2024-11-26 22:01:19 +01:00
rm -rf " $audioPath /incomplete/* "
2023-07-28 12:18:42 +02:00
NotifyWebhook "Error" "TIDAL not authenticated but configured"
tidalClientTest = "failed"
2024-04-28 05:28:26 +02:00
log " Script sleeping for $audioScriptInterval ... "
sleep $audioScriptInterval
2023-07-28 12:18:42 +02:00
exit
else
2024-11-26 22:01:19 +01:00
rm -rf " $audioPath /incomplete/* "
2023-07-28 12:18:42 +02:00
log "TIDAL :: Successfully Verified"
tidalClientTest = "success"
fi
}
2024-11-26 22:01:19 +01:00
logDl ( ) {
log " $page :: $wantedAlbumListSource :: $processNumber of $wantedListAlbumTotal :: \
$lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: $1 "
}
2023-07-11 14:14:37 +02:00
DownloadProcess ( ) {
# Required Input Data
# $1 = Album ID to download from online Service
# $2 = Download Client Type (DEEZER or TIDAL)
# $3 = Album Year that matches Album ID Metadata
# $4 = Album Title that matches Album ID Metadata
# $5 = Expected Track Count
# Create Required Directories
2023-07-15 22:26:48 +02:00
if [ ! -d " $audioPath /incomplete " ] ; then
2024-11-26 22:01:19 +01:00
mkdir -p " $audioPath /incomplete "
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
rm -rf " $audioPath /incomplete/* "
2023-07-11 14:14:37 +02:00
fi
2023-07-15 22:26:48 +02:00
if [ ! -d " $audioPath /complete " ] ; then
2024-11-26 22:01:19 +01:00
mkdir -p " $audioPath /complete "
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
rm -rf " $audioPath /complete/* "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
logPaths = ( "deezer" "tidal" "failed/deezer" "failed/tidal" )
for p in " ${ !logPaths[@] } " ; do
if [ ! -d " ${ STATE_DIR } /extended/logs/downloaded/ ${ logPaths [ $p ] } " ] ; then
mkdir -p " ${ STATE_DIR } /extended/logs/downloaded/ ${ logPaths [ $p ] } "
fi
done
2023-07-11 14:14:37 +02:00
2024-04-06 22:12:21 +02:00
if [ ! -d " $importPath " ] ; then
mkdir -p " $importPath "
fi
AddDownloadClient
2023-07-11 14:14:37 +02:00
downloadedAlbumTitleClean = " $( echo " $4 " | sed -e "s%[^[:alpha:][:digit:]._' ]% %g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' ) "
2024-11-26 22:01:19 +01:00
if find " $audioPath /complete " -type d -iname " $lidarrArtistNameSanitized - $downloadedAlbumTitleClean ( $3 )-*- $1 - $2 " | read -r; then
logDl "ERROR :: Previously Downloaded..."
2023-07-11 14:14:37 +02:00
return
fi
# check for log file
2024-11-26 22:01:19 +01:00
for i in "DEEZER" "TIDAL" ; do
if [ " $2 " = = $i ] ; then
if [ -f " ${ STATE_DIR } /extended/logs/downloaded/ ${ i ,, } / $1 " ] ; then
logDl " ERROR :: Previously Downloaded ( $1 )... "
return
fi
if [ -f " ${ STATE_DIR } /extended/logs/downloaded/failed/ ${ i ,, } / $1 " ] ; then
logDl " ERROR :: Previously Attempted Download ( $1 )... "
return
fi
fi
done
2023-07-11 14:14:37 +02:00
downloadTry = 0
until false
do
2024-11-26 22:01:19 +01:00
downloadTry = $(( downloadTry + 1 ))
if [ -f /tmp/temp-download ] ; then
rm /tmp/temp-download
2023-07-11 14:14:37 +02:00
sleep 0.1
fi
2024-11-26 22:01:19 +01:00
touch /tmp/temp-download
2023-07-11 14:14:37 +02:00
sleep 0.1
2024-11-26 22:01:19 +01:00
logDl " Download Attempt number $downloadTry "
2023-07-11 14:14:37 +02:00
if [ " $2 " = = "DEEZER" ] ; then
2024-11-26 22:01:19 +01:00
if [ -z " $arlToken " ] ; then
DownloadClientFreyr " $1 "
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
deemix -b $deemixQuality -p " $audioPath " /incomplete " https://www.deezer.com/album/ $1 " 2>& 1
2023-07-11 14:14:37 +02:00
fi
if [ -d "/tmp/deemix-imgs" ] ; then
rm -rf /tmp/deemix-imgs
fi
# Verify Client Works...
2023-07-15 22:26:48 +02:00
clientTestDlCount = $( find " $audioPath " /incomplete/ -type f -regex ".*/.*\.\(flac\|opus\|m4a\|mp3\)" | wc -l)
2024-11-26 22:01:19 +01:00
if [ " $clientTestDlCount " -le 0 ] ; then
2023-07-11 14:14:37 +02:00
# Add +1 to failed attempts
2024-11-26 22:01:19 +01:00
deemixFail = $(( deemixFail + 1 ))
2023-07-11 14:14:37 +02:00
else
# Reset for successful download
deemixFail = 0
fi
2023-07-28 11:47:18 +02:00
# If download failes X times, exit with error...
2024-11-26 22:01:19 +01:00
if [ $deemixFail -eq $failedDownloadAttemptThreshold ] && [ -z " $arlToken " ] ; then
rm -rf " $audioPath " /incomplete/*
logDl " All $failedDownloadAttemptThreshold Download Attempts failed, skipping... "
else
DeezerClientTest
if [ " $deezerClientTest " = = "success" ] ; then
logDl " All $failedDownloadAttemptThreshold Download Attempts failed, skipping... "
deemixFail = 0
2023-07-28 12:18:42 +02:00
fi
2023-07-11 14:14:37 +02:00
fi
fi
2024-11-26 22:01:19 +01:00
if [ " $2 " = = "DEEZER" ] && [ $deemixFail -eq $failedDownloadAttemptThreshold ] && [ -z " $arlToken " ] ; then
DownloadClientFreyr " $1 "
else
deemix -b $deemixQuality -p " $audioPath " /incomplete " https://www.deezer.com/album/ $1 " 2>& 1
fi
2023-08-15 16:07:49 +02:00
2023-07-11 14:14:37 +02:00
if [ " $2 " = = "TIDAL" ] ; then
TidaldlStatusCheck
2024-11-26 22:01:19 +01:00
tidal-dl -q $tidalQuality -o " $audioPath /incomplete " -l " $1 " 2>& 1
2023-07-11 14:14:37 +02:00
# Verify Client Works...
2023-07-15 22:26:48 +02:00
clientTestDlCount = $( find " $audioPath " /incomplete/ -type f -regex ".*/.*\.\(flac\|opus\|m4a\|mp3\)" | wc -l)
2024-11-26 22:01:19 +01:00
if [ " $clientTestDlCount " -le 0 ] ; then
2023-07-11 14:14:37 +02:00
# Add +1 to failed attempts
2024-11-26 22:01:19 +01:00
tidaldlFail = $(( tidaldlFail + 1 ))
2023-07-11 14:14:37 +02:00
else
# Reset for successful download
tidaldlFail = 0
fi
2023-07-28 11:47:18 +02:00
# If download failes X times, exit with error...
if [ $tidaldlFail -eq $failedDownloadAttemptThreshold ] ; then
2024-11-26 22:01:19 +01:00
TidalClientTest
if [ " $tidalClientTest " = = "success" ] ; then
logDl " All $failedDownloadAttemptThreshold Download Attempts failed, skipping... "
2023-07-11 14:14:37 +02:00
fi
fi
fi
2024-11-26 22:01:19 +01:00
find " $audioPath /incomplete " -type f -iname "*.flac" -newer "/tmp/temp-download" -print0 | while IFS = read -r -d '' file; do
2023-07-11 14:14:37 +02:00
audioFlacVerification " $file "
if [ " $verifiedFlacFile " = = "0" ] ; then
2024-11-26 22:01:19 +01:00
logDl " Flac Verification :: $file :: Verified "
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
logDl " Flac Verification :: $file :: ERROR :: Failed Verification "
2023-07-11 14:14:37 +02:00
rm " $file "
fi
done
2023-07-15 22:26:48 +02:00
downloadCount = $( find " $audioPath " /incomplete/ -type f -regex ".*/.*\.\(flac\|m4a\|mp3\)" | wc -l)
2023-07-11 14:14:37 +02:00
if [ " $downloadCount " -ne " $5 " ] ; then
2024-11-26 22:01:19 +01:00
logDl "ERROR :: download failed, missing tracks..."
2023-07-11 14:14:37 +02:00
completedVerification = "false"
else
2024-11-26 22:01:19 +01:00
logDl "Success"
2023-07-11 14:14:37 +02:00
completedVerification = "true"
fi
if [ " $completedVerification " = = "true" ] ; then
break
elif [ " $downloadTry " = = "2" ] ; then
2023-07-15 22:26:48 +02:00
if [ -d " $audioPath " /incomplete ] ; then
rm -rf " $audioPath " /incomplete/*
2023-07-11 14:14:37 +02:00
fi
break
else
2024-11-26 22:01:19 +01:00
logDl "Retry Download in 1 second fix errors..."
2023-07-11 14:14:37 +02:00
sleep 1
fi
done
# Consolidate files to a single folder
2024-11-26 22:01:19 +01:00
logDl "Consolidating files to single folder"
2023-07-18 23:08:53 +02:00
find " $audioPath /incomplete " -type f -exec mv "{}" " $audioPath " /incomplete/ \; 2>/dev/null
find $audioPath /incomplete/ -type d -mindepth 1 -maxdepth 1 -exec rm -rf { } \; 2>/dev/null
2023-07-11 14:14:37 +02:00
2023-07-15 22:26:48 +02:00
downloadCount = $( find " $audioPath " /incomplete/ -type f -regex ".*/.*\.\(flac\|m4a\|mp3\)" | wc -l)
2023-07-11 14:14:37 +02:00
if [ " $downloadCount " -gt "0" ] ; then
# Check download for required quality (checks based on file extension)
2023-07-15 22:26:48 +02:00
DownloadQualityCheck " $audioPath /incomplete " " $2 "
2023-07-11 14:14:37 +02:00
fi
2023-07-15 22:26:48 +02:00
downloadCount = $( find " $audioPath " /incomplete/ -type f -regex ".*/.*\.\(flac\|m4a\|mp3\)" | wc -l)
2023-07-11 14:14:37 +02:00
if [ " $downloadCount " -ne " $5 " ] ; then
2024-11-26 22:01:19 +01:00
logDl "ERROR :: All download Attempts failed..."
logDl " Logging $1 as failed download... "
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
for awa in "DEEZER" "TIDAL" ; do
[ " $2 " = = $awa ] \
&& touch " ${ STATE_DIR } /extended/logs/downloaded/failed/ ${ awa ,, } / $1 "
done
2023-07-11 14:14:37 +02:00
return
fi
# Log Completed Download
2024-11-26 22:01:19 +01:00
logDl " Logging $1 as successfully downloaded... "
for awa in "DEEZER" "TIDAL" ; do
[ " $2 " = = $awa ] \
&& touch " ${ STATE_DIR } /extended/logs/downloaded/ ${ awa ,, } / $1 "
done
2023-07-11 14:14:37 +02:00
# Tag with beets
if [ " $enableBeetsTagging " = = "true" ] ; then
2024-11-26 22:01:19 +01:00
[ -f " ${ STATE_DIR } /extended/beets-error " ] && rm " ${ STATE_DIR } /extended/beets-error "
logDl "Processing files with beets..."
2023-07-15 22:26:48 +02:00
ProcessWithBeets " $audioPath /incomplete "
2023-07-11 14:14:37 +02:00
fi
# Embed Lyrics into Flac files
2023-07-15 22:26:48 +02:00
find " $audioPath /incomplete " -type f -iname "*.flac" -print0 | while IFS = read -r -d '' file; do
2023-07-11 14:14:37 +02:00
lrcFile = " ${ file %.* } .lrc "
if [ -f " $lrcFile " ] ; then
2024-11-26 22:01:19 +01:00
logDl " Embedding lyrics (lrc) into $file "
2023-07-11 14:14:37 +02:00
metaflac --remove-tag= Lyrics " $file "
metaflac --set-tag-from-file= " Lyrics= $lrcFile " " $file "
fi
done
if [ " $audioFormat " != "native" ] ; then
2024-11-26 22:01:19 +01:00
logDl " Converting Flac Audio to ${ audioFormat ^^ } ( $audioBitrateText ) "
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
[ " $audioFormat " = = "opus" ] \
&& options = " -c:a libopus -b:a ${ audioBitrate } k -application audio -vbr off " \
&& extension = $audioFormat
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
[ " $audioFormat " = = "mp3" ] \
&& options = " -c:a libmp3lame -b:a ${ audioBitrate } k " \
&& extension = $audioFormat
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
[ " $audioFormat " = = "aac" ] \
&& options = " -c:a aac -b:a ${ audioBitrate } k -movflags faststart " \
&& extension = "m4a"
[ " $audioFormat " = = "alac" ] \
&& options = "-c:a alac -movflags faststart" \
&& extension = "m4a"
2023-07-11 14:14:37 +02:00
2023-07-15 22:26:48 +02:00
find " $audioPath /incomplete " -type f -iname "*.flac" -print0 | while IFS = read -r -d '' audio; do
2023-07-11 14:14:37 +02:00
file = " ${ audio } "
filename = " $( basename " $audio " ) "
foldername = " $( dirname " $audio " ) "
filenamenoext = " ${ filename %.* } "
if [ " $audioFormat " = = "opus" ] ; then
if opusenc --bitrate ${ audioBitrate } --vbr --music " $file " " $foldername / ${ filenamenoext } . $extension " ; then
2024-11-26 22:01:19 +01:00
logDl " $filename :: Conversion to $audioFormat ( $audioBitrateText ) successful "
2023-07-11 14:14:37 +02:00
rm " $file "
else
2024-11-26 22:01:19 +01:00
logDl " $filename :: ERROR :: Conversion Failed "
2023-07-11 14:14:37 +02:00
rm " $foldername / ${ filenamenoext } . $extension "
fi
continue
fi
2024-11-26 22:01:19 +01:00
if ffmpeg -loglevel warning -hide_banner -nostats -i " $file " -n -vn " $options " " $foldername / ${ filenamenoext } . $extension " < /dev/null; then
logDl " $filename :: Conversion to $audioFormat ( $audioBitrateText ) successful "
2023-07-11 14:14:37 +02:00
rm " $file "
else
2024-11-26 22:01:19 +01:00
logDl " $filename :: ERROR :: Conversion Failed "
2023-07-11 14:14:37 +02:00
rm " $foldername / ${ filenamenoext } . $extension "
fi
done
fi
if [ " $enableReplaygainTags " = = "true" ] ; then
2023-07-15 22:26:48 +02:00
AddReplaygainTags " $audioPath /incomplete "
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
logDl "Replaygain Tagging Disabled (set enableReplaygainTags=true to enable...)"
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
albumquality = " $( find " $audioPath " /incomplete/ -type f -regex ".*/.*\.\(flac\|opus\|m4a\|mp3\)" | head -n 1 | grep -i -E -o " \.{1}\w* $" | sed 's/\.//g' ) "
2024-04-06 22:12:21 +02:00
downloadedAlbumFolder = " ${ lidarrArtistNameSanitized } - ${ downloadedAlbumTitleClean : 0 : 100 } ( ${ 3 } ) "
2023-07-11 14:14:37 +02:00
2023-07-15 22:26:48 +02:00
find " $audioPath /incomplete " -type f -regex ".*/.*\.\(flac\|opus\|m4a\|mp3\)" -print0 | while IFS = read -r -d '' audio; do
2023-07-11 14:14:37 +02:00
file = " ${ audio } "
filenoext = " ${ file %.* } "
filename = " $( basename " $audio " ) "
extension = " ${ filename ##*. } "
filenamenoext = " ${ filename %.* } "
2023-07-15 22:26:48 +02:00
if [ ! -d " $audioPath /complete " ] ; then
mkdir -p " $audioPath " /complete
chmod 777 " $audioPath " /complete
2023-07-11 14:14:37 +02:00
fi
2023-07-15 22:26:48 +02:00
mkdir -p " $audioPath /complete/ $downloadedAlbumFolder "
mv " $file " " $audioPath /complete/ $downloadedAlbumFolder " /
2023-07-11 14:14:37 +02:00
done
2023-07-15 22:26:48 +02:00
chmod -R 777 " $audioPath " /complete
2024-04-06 22:12:21 +02:00
mv " $audioPath /complete/ $downloadedAlbumFolder " " $importPath "
2024-04-12 10:38:27 +02:00
if [ -d " $importPath / $downloadedAlbumFolder " ] ; then
NotifyLidarrForImport " $importPath / $downloadedAlbumFolder "
2023-09-22 00:42:57 +02:00
lidarrDownloadImportNotfication = "true"
2023-07-11 14:14:37 +02:00
LidarrTaskStatusCheck
fi
2023-07-15 22:26:48 +02:00
if [ -d " $audioPath /complete/ $downloadedAlbumFolder " ] ; then
rm -rf " $audioPath " /incomplete/*
2023-07-11 14:14:37 +02:00
fi
}
ProcessWithBeets ( ) {
# Input
# $1 Download Folder to process
2024-11-26 22:01:19 +01:00
for awa in "extended/beets-library.blb" "extended/beets.log" "beets-match" ; do
[ -f " ${ STATE_DIR } / ${ awa } " ] \
&& rm " ${ STATE_DIR } / ${ awa } " \
&& sleep 0.5
done
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
touch " ${ STATE_DIR } /beets-match "
2023-07-11 14:14:37 +02:00
sleep 0.5
2024-11-26 22:01:19 +01:00
beet -c " ${ STATE_DIR } /extended/beets-config.yaml " \
-l " ${ STATE_DIR } /extended/beets-library.blb " -d " $1 " import -qC " $1 "
if [ " $( find " $1 " -type f -regex ".*/.*\.\(flac\|opus\|m4a\|mp3\)" -newer " ${ STATE_DIR } /beets-match " | wc -l) " -gt 0 ] ; then
logDl "SUCCESS: Matched with beets!"
logDl "fixing track tags"
2023-07-15 22:26:48 +02:00
find " $audioPath /incomplete " -type f -iname "*.flac" -print0 | while IFS = read -r -d '' file; do
2023-07-11 14:14:37 +02:00
getArtistCredit = " $( ffprobe -loglevel 0 -print_format json -show_format -show_streams " $file " | jq -r ".format.tags.ARTIST_CREDIT" | sed "s/null//g" | sed " /^ $/d " ) "
2023-09-08 18:34:25 +02:00
# album artist
2024-11-26 22:01:19 +01:00
metaflac \
--remove-tag= ALBUMARTIST --remove-tag= ALBUMARTIST_CREDIT --remove-tag= ALBUM_ARTIST \
--remove-tag= "ALBUM ARTIST" --remove-tag= ARTIST --remove-tag= ARTIST_CREDIT \
--remove-tag= ARTISTSORT --remove-tag= COMPOSERSORT --remove-tag= ALBUMARTISTSORT \
--remove-tag= MUSICBRAINZ_ARTISTID --remove-tag= MUSICBRAINZ_ALBUMARTISTID \
" $file "
metaflac \
--set-tag= ALBUMARTIST = " $lidarrArtistName " \
--set-tag= MUSICBRAINZ_ARTISTID = " $lidarrArtistForeignArtistId " \
--set-tag= MUSICBRAINZ_ALBUMARTISTID = " $lidarrArtistForeignArtistId " \
" $file "
if [ -n " $getArtistCredit " ] ; then
metaflac --set-tag= ARTIST = " $getArtistCredit " " $file "
2023-09-08 18:34:25 +02:00
else
metaflac --set-tag= ARTIST = " $lidarrArtistName " " $file "
fi
2024-11-26 22:01:19 +01:00
log " FIXED : $file "
2023-07-11 14:14:37 +02:00
done
else
2024-11-26 22:01:19 +01:00
log "ERROR :: Unable to match using beets to a musicbrainz release..."
2023-07-11 14:14:37 +02:00
return
fi
2024-11-26 22:01:19 +01:00
[ -f " ${ STATE_DIR } /beets-match " ] \
&& rm " ${ STATE_DIR } /beets-match " \
&& sleep 0.1
2023-07-11 14:14:37 +02:00
# Get file metadata
2023-07-15 22:26:48 +02:00
GetFile = $( find " $audioPath /incomplete " -type f -regex ".*/.*\.\(flac\|opus\|m4a\|mp3\)" | head -n1)
2023-07-11 14:14:37 +02:00
extension = " ${ GetFile ##*. } "
2024-11-26 22:01:19 +01:00
ffprobeGet = $( ffprobe -hide_banner -loglevel fatal -show_error -show_format -show_streams \
-show_programs -show_chapters -show_private_data -print_format json \
" $GetFile "
)
2023-07-11 14:14:37 +02:00
if [ " $extension " = = "opus" ] ; then
2024-11-26 22:01:19 +01:00
matchedTags = $( ${ ffprobeGet } | jq -r ".streams[].tags" )
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
matchedTags = $( ${ ffprobeGet } | jq -r ".format.tags" )
2023-07-11 14:14:37 +02:00
fi
# Get Musicbrainz Release Group ID and Album Artist ID from tagged file
if [ " $extension " = = "flac" ] || [ " $extension " = = "opus" ] ; then
2024-11-26 22:01:19 +01:00
matchedTagsAlbumReleaseGroupId = " $( echo " $matchedTags " | jq -r ".MUSICBRAINZ_RELEASEGROUPID" ) "
matchedTagsAlbumArtistId = " $( echo " $matchedTags " | jq -r ".MUSICBRAINZ_ALBUMARTISTID" ) "
2023-07-11 14:14:37 +02:00
elif [ " $extension " = = "mp3" ] || [ " $extension " = = "m4a" ] ; then
2024-11-26 22:01:19 +01:00
matchedTagsAlbumReleaseGroupId = " $( echo " $matchedTags " | jq -r '."MusicBrainz Release Group Id"' ) "
matchedLidarrAlbumArtistId = " $( echo " $matchedTags " | jq -r '."MusicBrainz Ablum Artist Id"' ) "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
[ ! -d " ${ STATE_DIR } /extended/logs/downloaded/musicbrainz_matched " ] \
&& mkdir -p " ${ STATE_DIR } /extended/logs/downloaded/musicbrainz_matched "
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
[ ! -f " ${ STATE_DIR } /extended/logs/downloaded/musicbrainz_matched/ $matchedTagsAlbumReleaseGroupId " ] \
&& log " Marking MusicBrainz Release Group ( $matchedTagsAlbumReleaseGroupId ) as successfully downloaded... " \
&& touch " ${ STATE_DIR } /extended/logs/downloaded/musicbrainz_matched/ $matchedTagsAlbumReleaseGroupId "
2024-08-05 13:12:51 +02:00
2023-07-11 14:14:37 +02:00
}
DownloadQualityCheck ( ) {
2024-11-26 22:01:19 +01:00
[ " $requireQuality " != "true" ] \
&& logDl "Skipping download quality check... (enable by setting: requireQuality=true)" \
&& return
logDl "Checking for unwanted files"
local deezer
local tidal
local other
local notNative
notNative = $( [ " $audioFormat " != "native" ] \
&& find " $1 " -type f -regex ".*/.*\.\(opus\|m4a\|mp3\)" | read -r
)
other = $( [ " $audioBitrate " = = "master" ] || [ " $audioBitrate " = = "lossless" ] \
&& find " $1 " -type f -regex ".*/.*\.\(opus\|m4a\|mp3\)" | read -r
)
deezer = $( [ " $2 " = = "DEEZER" ] \
&& find " $1 " -type f -regex ".*/.*\.\(opus\|m4a\|flac\)" | read -r
)
tidal = $( [ " $2 " = = "TIDAL" ] \
&& find " $1 " -type f -regex ".*/.*\.\(opus\|flac\|mp3\)" | read -r
)
if $notNative || $deezer || $tidal || $other ; then
logDl "Unwanted files found!"
logDl "Performing cleanup..."
rm " $1 " /*
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
logDl "No unwanted files found!"
2023-07-11 14:14:37 +02:00
fi
}
AddReplaygainTags ( ) {
# Input Data
# $1 Folder path to scan and add tags
2024-11-26 22:01:19 +01:00
logDl "Adding Replaygain Tags using r128gain"
2023-07-11 14:14:37 +02:00
r128gain -r -c 1 -a " $1 " & >/dev/null
}
NotifyLidarrForImport ( ) {
2024-11-26 22:01:19 +01:00
curl -s " $arrUrl /api/v1/command " --header "X-Api-Key:" " ${ arrApiKey } " -H "Content-Type: application/json" --data " {\"name\":\"DownloadedAlbumsScan\", \"path\":\" $1 \"} "
logDl " LIDARR IMPORT NOTIFICATION SENT! :: $1 "
2023-07-11 14:14:37 +02:00
}
DeemixClientSetup ( ) {
log "DEEZER :: Verifying deemix configuration"
2024-11-26 22:01:19 +01:00
if [ -n " $arlToken " ] ; then
arlToken = " $( echo " $arlToken " | sed -e "s%[^[:alpha:][:digit:]]%%g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' ) "
2023-07-11 14:14:37 +02:00
# Create directories
2024-11-26 22:01:19 +01:00
mkdir -p " ${ STATE_DIR } /xdg/deemix "
if [ -f " ${ STATE_DIR } /xdg/deemix/.arl " ] ; then
rm " ${ STATE_DIR } /xdg/deemix/.arl "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
if [ ! -f " ${ STATE_DIR } /xdg/deemix/.arl " ] ; then
echo -n " $arlToken " > " / ${ STATE_DIR } /xdg/deemix/.arl "
2023-07-11 14:14:37 +02:00
fi
log "DEEZER :: ARL Token: Configured"
else
log " DEEZER :: ERROR :: arlToken setting invalid, currently set to: $arlToken "
fi
2024-11-26 22:01:19 +01:00
if [ -f " ${ STATE_DIR } /xdg/deemix/config.json " ] ; then
rm " ${ STATE_DIR } /xdg/deemix/config.json "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
if [ -f " ${ STATE_DIR } /extended/deemix_config.json " ] ; then
2023-07-11 14:14:37 +02:00
log "DEEZER :: Configuring deemix client"
2024-11-26 22:01:19 +01:00
cp " ${ STATE_DIR } /extended/deemix_config.json " " ${ STATE_DIR } /xdg/deemix/config.json "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
if [ -d " ${ STATE_DIR } /extended/cache/deezer " ] ; then
2023-07-11 14:14:37 +02:00
log "DEEZER :: Purging album list cache..."
2024-11-26 22:01:19 +01:00
rm " ${ STATE_DIR } /extended/cache/deezer/*-albums.json " & >/dev/null
2023-07-11 14:14:37 +02:00
fi
2023-07-15 22:26:48 +02:00
if [ ! -d " $audioPath /incomplete " ] ; then
mkdir -p " $audioPath " /incomplete
2023-07-11 14:14:37 +02:00
else
2023-07-15 22:26:48 +02:00
rm -rf " $audioPath " /incomplete/*
2023-07-11 14:14:37 +02:00
fi
#log "DEEZER :: Upgrade deemix to the latest..."
#pip install deemix --upgrade &>/dev/null
}
2023-07-28 12:18:42 +02:00
DeezerClientTest ( ) {
log "DEEZER :: deemix client setup verification..."
2024-11-26 22:01:19 +01:00
deemix -b 128 -p $audioPath /incomplete " https://www.deezer.com/album/ $deezerClientTestDownloadId "
2023-07-28 12:18:42 +02:00
if [ -d "/tmp/deemix-imgs" ] ; then
rm -rf /tmp/deemix-imgs
fi
deezerClientTest = "unknown"
downloadCount = $( find $audioPath /incomplete/ -type f -regex ".*/.*\.\(flac\|opus\|m4a\|mp3\)" | wc -l)
2024-11-26 22:01:19 +01:00
if [ " $downloadCount " -le 0 ] ; then
2023-07-28 12:18:42 +02:00
log "DEEZER :: ERROR :: Download failed"
log "DEEZER :: ERROR :: Please review log for errors in client"
log "DEEZER :: ERROR :: Try updating your ARL Token to possibly resolve the issue..."
log "DEEZER :: ERROR :: Exiting..."
rm -rf $audioPath /incomplete/*
NotifyWebhook "Error" "DEEZER not authenticated but configured"
2024-11-26 22:01:19 +01:00
deezerClientTest = "fail"
2023-07-28 12:18:42 +02:00
exit
else
rm -rf $audioPath /incomplete/*
log "DEEZER :: Successfully Verified"
deezerClientTest = "success"
fi
}
2023-07-11 14:14:37 +02:00
LidarrRootFolderCheck ( ) {
2024-11-26 22:01:19 +01:00
if curl -s " $arrUrl /api/v1/rootFolder " -H " X-Api-Key: ${ arrApiKey } " | sed '1q' | grep "\[\]" | read -r; then
2023-07-11 14:14:37 +02:00
log "ERROR :: No root folder found"
log "ERROR :: Configure root folder in Lidarr to continue..."
log "ERROR :: Exiting..."
NotifyWebhook "FatalError" "No root folder found"
exit
fi
}
GetMissingCutOffList ( ) {
# Remove previous search missing/cutoff list
2024-11-26 22:01:19 +01:00
[ -d " ${ STATE_DIR } /extended/cache/lidarr/list " ] \
&& rm -rf " ${ STATE_DIR } /extended/cache/lidarr/list " \
&& sleep 0.1
2023-07-11 14:14:37 +02:00
# Create list folder if does not exist
2024-11-26 22:01:19 +01:00
mkdir -p " ${ STATE_DIR } /extended/cache/lidarr/list "
2023-07-11 14:14:37 +02:00
# Create notfound log folder if does not exist
2024-11-26 22:01:19 +01:00
[ ! -d " ${ STATE_DIR } /extended/logs/notfound " ] \
&& mkdir -p " ${ STATE_DIR } /extended/logs/notfound "
2023-07-11 14:14:37 +02:00
# Configure searchSort preferences based on settings
if [ " $searchSort " = = "date" ] ; then
searchOrder = "releaseDate"
searchDirection = "descending"
2024-11-26 22:01:19 +01:00
elif [ " $searchSort " = = "album" ] ; then
2023-07-11 14:14:37 +02:00
searchOrder = "albumType"
searchDirection = "ascending"
fi
2023-07-11 15:41:58 +02:00
lidarrMissingTotalRecords = $( wget --timeout= 0 -q -O - " $arrUrl /api/v1/wanted/missing?page=1&pagesize=1&sortKey= $searchOrder &sortDirection= $searchDirection &apikey= ${ arrApiKey } " | jq -r .totalRecords)
2023-07-11 14:14:37 +02:00
log " FINDING MISSING ALBUMS :: sorted by $searchSort "
amountPerPull = 1000
page = 0
log " $lidarrMissingTotalRecords Missing Albums Found! "
log "Getting Missing Album IDs"
2024-11-26 22:01:19 +01:00
if [ " $lidarrMissingTotalRecords " -ge 1 ] ; then
offsetcount = $(( lidarrMissingTotalRecords / amountPerPull ))
for ( ( i = 0; i<= offsetcount; i++) ) ; do
page = $(( i + 1 ))
offset = $(( i * amountPerPull ))
dlnumber = $(( offset + amountPerPull ))
2023-07-11 14:14:37 +02:00
if [ " $dlnumber " -gt " $lidarrMissingTotalRecords " ] ; then
dlnumber = " $lidarrMissingTotalRecords "
fi
log " $page :: missing :: Downloading page $page ... ( $offset - $dlnumber of $lidarrMissingTotalRecords Results) "
2023-10-14 20:00:20 +02:00
2024-11-26 22:01:19 +01:00
wget --timeout= 0 -q -O - \
" $arrUrl /api/v1/wanted/missing?page= $page &pagesize= $amountPerPull &sortKey= $searchOrder &sortDirection= $searchDirection &apikey= ${ arrApiKey } " \
| jq -r '.records[].id' \
| sort > " ${ STATE_DIR } /extended/cache/tocheck.txt "
log " $page :: missing :: Filtering Album IDs by removing previously searched Album IDs ( ${ STATE_DIR } /extended/logs/notfound/<files>) "
ls " ${ STATE_DIR } /extended/logs/notfound/ " | sed "s/--.*//" > " ${ STATE_DIR } /extended/cache/notfound.txt "
for lidarrRecordId in $( comm -13 " ${ STATE_DIR } /extended/cache/notfound.txt " " ${ STATE_DIR } /extended/cache/tocheck.txt " ) ; do
for f in " ${ STATE_DIR } " /extended/logs/notfound/" $lidarrRecordId " --*; do
if [ ! -f " $f " ] ; then
touch " ${ STATE_DIR } /extended/cache/lidarr/list/ ${ lidarrRecordId } -missing "
fi
done
2023-07-11 14:14:37 +02:00
done
2024-11-26 22:01:19 +01:00
rm " ${ STATE_DIR } /extended/cache/notfound.txt " " ${ STATE_DIR } /extended/cache/tocheck.txt "
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
lidarrMissingRecords = $( ls " ${ STATE_DIR } /extended/cache/lidarr/list " 2>/dev/null | wc -l)
2023-07-11 14:14:37 +02:00
log " $page :: missing :: ${ lidarrMissingRecords } albums found to process! "
wantedListAlbumTotal = $lidarrMissingRecords
2024-11-26 22:01:19 +01:00
if [ " ${ lidarrMissingRecords } " -gt 0 ] ; then
2023-07-11 14:14:37 +02:00
log " $page :: missing :: Searching for $wantedListAlbumTotal items "
SearchProcess
2024-11-26 22:01:19 +01:00
rm " ${ STATE_DIR } /extended/cache/lidarr/list/*-missing "
2023-07-11 14:14:37 +02:00
fi
done
fi
# Get cutoff album list
2024-11-26 22:01:19 +01:00
lidarrCutoffTotalRecords = $( wget --timeout= 0 -q -O - \
" $arrUrl /api/v1/wanted/cutoff?page=1&pagesize=1&sortKey= $searchOrder &sortDirection= $searchDirection &apikey= ${ arrApiKey } " \
| jq -r .totalRecords
)
2023-07-11 14:14:37 +02:00
log " FINDING CUTOFF ALBUMS sorted by $searchSort "
log " $lidarrCutoffTotalRecords CutOff Albums Found Found! "
log "Getting CutOff Album IDs"
2024-11-26 22:01:19 +01:00
2023-07-11 14:14:37 +02:00
page = 0
2024-11-26 22:01:19 +01:00
if [ " $lidarrCutoffTotalRecords " -ge 1 ] ; then
offsetcount = $(( lidarrCutoffTotalRecords / amountPerPull ))
for ( ( i = 0; i<= offsetcount; i++) ) ; do
page = $(( i + 1 ))
offset = $(( i * amountPerPull ))
dlnumber = $(( offset + amountPerPull ))
2023-07-11 14:14:37 +02:00
if [ " $dlnumber " -gt " $lidarrCutoffTotalRecords " ] ; then
dlnumber = " $lidarrCutoffTotalRecords "
fi
log " $page :: cutoff :: Downloading page $page ... ( $offset - $dlnumber of $lidarrCutoffTotalRecords Results) "
2023-10-14 20:00:20 +02:00
# lidarrRecords=$(wget --timeout=0 -q -O - "$arrUrl/api/v1/wanted/cutoff?page=$page&pagesize=$amountPerPull&sortKey=$searchOrder&sortDirection=$searchDirection&apikey=${arrApiKey}" | jq -r '.records[].id')
2024-11-26 22:01:19 +01:00
wget --timeout= 0 -q -O - \
" $arrUrl /api/v1/wanted/cutoff?page= $page &pagesize= $amountPerPull &sortKey= $searchOrder &sortDirection= $searchDirection &apikey= ${ arrApiKey } " \
| jq -r '.records[].id' \
| sort > " ${ STATE_DIR } /extended/cache/tocheck.txt "
log " $page :: cutoff :: Filtering Album IDs by removing previously searched Album IDs ( ${ STATE_DIR } /extended/logs/notfound/<files>) "
ls " ${ STATE_DIR } /extended/logs/notfound/ " | sed "s/--.*//" > " ${ STATE_DIR } /extended/cache/notfound.txt "
for lidarrRecordId in $( comm -13 " ${ STATE_DIR } /extended/cache/notfound.txt " " ${ STATE_DIR } /extended/cache/tocheck.txt " ) ; do
for f in " ${ STATE_DIR } " /extended/logs/notfound/" $lidarrRecordId " --*; do
if [ ! -f " $f " ] ; then
touch " ${ STATE_DIR } /extended/cache/lidarr/list/ ${ lidarrRecordId } -missing "
fi
done
2023-07-11 14:14:37 +02:00
done
2024-11-26 22:01:19 +01:00
rm " ${ STATE_DIR } /extended/cache/notfound.txt " " ${ STATE_DIR } /extended/cache/tocheck.txt "
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
local cutoffFiles
cutoffFiles = ( " ${ STATE_DIR } /extended/cache/lidarr/list/*-cutoff " )
lidarrCutoffRecords = ${# cutoffFiles [@] }
2024-05-31 19:53:05 +02:00
log " $page :: cutoff :: ${ lidarrCutoffRecords } albums found to process! "
2023-07-11 14:14:37 +02:00
wantedListAlbumTotal = $lidarrCutoffRecords
2024-11-26 22:01:19 +01:00
if [ " ${ lidarrCutoffRecords } " -gt 0 ] ; then
2023-07-11 14:14:37 +02:00
log " $page :: cutoff :: Searching for $wantedListAlbumTotal items "
SearchProcess
2024-11-26 22:01:19 +01:00
rm " ${ STATE_DIR } /extended/cache/lidarr/list/*-cutoff "
2023-07-11 14:14:37 +02:00
fi
done
fi
}
SearchProcess ( ) {
if [ " $wantedListAlbumTotal " = = "0" ] ; then
log "No items to find, end"
return
fi
processNumber = 0
2024-11-26 22:01:19 +01:00
for lidarrMissingId in $( ls -tr " ${ STATE_DIR } /extended/cache/lidarr/list " ) ; do
processNumber = $(( processNumber + 1 ))
wantedAlbumId = $( echo " $lidarrMissingId " | sed -e "s%[^[:digit:]]%%g" )
2023-07-11 14:14:37 +02:00
checkLidarrAlbumId = $wantedAlbumId
wantedAlbumListSource = $( echo $lidarrMissingId | sed -e "s%[^[:alpha:]]%%g" )
2023-07-11 15:41:58 +02:00
lidarrAlbumData = " $( curl -s " $arrUrl /api/v1/album/ $wantedAlbumId ?apikey= ${ arrApiKey } " ) "
2023-07-11 14:14:37 +02:00
lidarrArtistData = $( echo " ${ lidarrAlbumData } " | jq -r ".artist" )
lidarrArtistName = $( echo " ${ lidarrArtistData } " | jq -r ".artistName" )
lidarrArtistForeignArtistId = $( echo " ${ lidarrArtistData } " | jq -r ".foreignArtistId" )
lidarrAlbumType = $( echo " $lidarrAlbumData " | jq -r ".albumType" )
lidarrAlbumTitle = $( echo " $lidarrAlbumData " | jq -r ".title" )
lidarrAlbumForeignAlbumId = $( echo " $lidarrAlbumData " | jq -r ".foreignAlbumId" )
LidarrTaskStatusCheck
2024-11-26 22:01:19 +01:00
[ -f " ${ STATE_DIR } /extended/logs/notfound/ $wantedAlbumId -- $lidarrArtistForeignArtistId -- $lidarrAlbumForeignAlbumId " ] \
&& logDl " $wantedAlbumListSource :: $lidarrArtistName :: $lidarrAlbumTitle :: Previously Not Found, skipping... " \
&& continue
# Skip Video Check for Various Artists album searches because videos are not supported...
if [ " $enableVideo " = = "true" ] \
&& [ " $lidarrArtistForeignArtistId " != "89ad4ac3-39f7-470e-963a-56509c546377" ] \
&& [ -d " ${ STATE_DIR } /extended/logs/video/complete " ] \
&& [ ! -f " ${ STATE_DIR } /extended/logs/video/complete/ $lidarrArtistForeignArtistId " ] ; then
logDl " $wantedAlbumListSource :: $lidarrArtistName :: $lidarrAlbumTitle :: Skipping until all videos are processed for the artist... "
continue
else
logDl " $wantedAlbumListSource :: $lidarrArtistName :: $lidarrAlbumTitle :: Skipping until all videos are processed for the artist... "
2023-07-11 14:14:37 +02:00
continue
fi
2024-11-26 22:01:19 +01:00
if [ -f " ${ STATE_DIR } /extended/logs/downloaded/notfound/ $lidarrAlbumForeignAlbumId " ] ; then
logDL "Previously Not Found, skipping..."
rm " ${ STATE_DIR } /extended/logs/downloaded/notfound/ $lidarrAlbumForeignAlbumId "
touch " ${ STATE_DIR } /extended/logs/notfound/ $wantedAlbumId -- $lidarrArtistForeignArtistId -- $lidarrAlbumForeignAlbumId "
2023-07-11 14:14:37 +02:00
continue
fi
lidarrAlbumTitleClean = $( echo " $lidarrAlbumTitle " | sed -e "s%[^[:alpha:][:digit:]]%%g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' )
lidarrAlbumTitleCleanSpaces = $( echo " $lidarrAlbumTitle " | sed -e "s%[^[:alpha:][:digit:]]% %g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' )
lidarrAlbumReleases = $( echo " $lidarrAlbumData " | jq -r ".releases" )
#echo $lidarrAlbumData | jq -r
lidarrAlbumWordCount = $( echo $lidarrAlbumTitle | wc -w)
#echo $lidarrAlbumReleases | jq -r
lidarrArtistData = $( echo " ${ lidarrAlbumData } " | jq -r ".artist" )
lidarrArtistId = $( echo " ${ lidarrArtistData } " | jq -r ".artistMetadataId" )
lidarrArtistPath = " $( echo " ${ lidarrArtistData } " | jq -r " .path" ) "
lidarrArtistFolder = " $( basename " ${ lidarrArtistPath } " ) "
lidarrArtistName = $( echo " ${ lidarrArtistData } " | jq -r ".artistName" )
lidarrArtistNameSanitized = " $( basename " ${ lidarrArtistPath } " | sed 's% (.*)$%%g' | sed 's/-/ /g' ) "
lidarrArtistNameSearchSanitized = " $( echo " $lidarrArtistName " | sed -e "s%[^[:alpha:][:digit:]]% %g" -e "s/ */ /g" ) "
albumArtistNameSearch = " $( jq -R -r @uri <<< " ${ lidarrArtistNameSearchSanitized } " ) "
lidarrArtistForeignArtistId = $( echo " ${ lidarrArtistData } " | jq -r ".foreignArtistId" )
tidalArtistUrl = $( echo " ${ lidarrArtistData } " | jq -r ".links | .[] | select(.name==\"tidal\") | .url" )
tidalArtistIds = " $( echo " $tidalArtistUrl " | grep -o '[[:digit:]]*' | sort -u) "
deezerArtistUrl = $( echo " ${ lidarrArtistData } " | jq -r ".links | .[] | select(.name==\"deezer\") | .url" )
lidarrAlbumReleaseIds = $( echo " $lidarrAlbumData " | jq -r ".releases | sort_by(.trackCount) | reverse | .[].id" )
lidarrAlbumReleasesMinTrackCount = $( echo " $lidarrAlbumData " | jq -r ".releases[].trackCount" | sort -n | head -n1)
lidarrAlbumReleasesMaxTrackCount = $( echo " $lidarrAlbumData " | jq -r ".releases[].trackCount" | sort -n -r | head -n1)
lidarrAlbumReleaseDate = $( echo " $lidarrAlbumData " | jq -r .releaseDate)
lidarrAlbumReleaseDate = ${ lidarrAlbumReleaseDate : 0 : 10 }
2024-11-26 22:01:19 +01:00
lidarrAlbumReleaseDateClean = " $( echo " $lidarrAlbumReleaseDate " | sed -e "s%[^[:digit:]]%%g" ) "
2023-07-11 14:14:37 +02:00
lidarrAlbumReleaseYear = " ${ lidarrAlbumReleaseDate : 0 : 4 } "
2024-11-26 22:01:19 +01:00
currentDate = " $( date "+%Y%m%d" ) "
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
if [ [ ${ currentDate } -ge ${ lidarrAlbumReleaseDateClean } ] ] ; then
skipNotFoundLogCreation = "false"
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
releaseDateComparisonInDays = $(( $(( \
$( date --date= " $currentDate " "+%s" ) - $( date --date= " $lidarrAlbumReleaseDateClean " "+%s" ) \
) ) / 60 / 60 / 24 \
) )
logDl "Starting Search..."
2023-07-11 14:14:37 +02:00
if [ $releaseDateComparisonInDays -lt 8 ] ; then
skipNotFoundLogCreation = "true"
fi
else
2024-11-26 22:01:19 +01:00
logDl " Album ( $lidarrAlbumReleaseDate ) has not been released, skipping... "
2023-07-11 14:14:37 +02:00
continue
fi
2024-11-26 22:01:19 +01:00
skipTidal = $( [ " $dlClientSource " != "tidal" ] && [ " $dlClientSource " != "both" ] )
skipDeezer = $( [ " $dlClientSource " != "deezer" ] && [ " $dlClientSource " != "both" ] )
2023-07-11 14:14:37 +02:00
if [ " $skipDeezer " = = "false" ] ; then
2024-11-26 22:01:19 +01:00
mapfile -t deezerArtistIds < <( echo " $deezerArtistUrl " | grep -o '[[:digit:]]*' | sort -u)
2023-07-11 14:14:37 +02:00
if [ -z " $deezerArtistUrl " ] ; then
2024-11-26 22:01:19 +01:00
log " DEEZER :: ERROR :: musicbrainz id: $lidarrArtistForeignArtistId is missing Deezer link, see: \
\" ${ STATE_DIR } /logs/deezer-artist-id-not-found.txt\" for more detail..."
touch " ${ STATE_DIR } /logs/deezer-artist-id-not-found.txt "
skipDeezer = true
if grep " https://musicbrainz.org/artist/ $lidarrArtistForeignArtistId /edit " " ${ STATE_DIR } /logs/deezer-artist-id-not-found.txt " | read -r; then
2023-07-11 14:14:37 +02:00
sleep 0.01
else
2024-11-26 22:01:19 +01:00
echo " Update Musicbrainz Relationship Page: \
https://musicbrainz.org/artist/$lidarrArtistForeignArtistId /edit for \" ${ lidarrArtistName } \" with Deezer Artist Link" \
>> " ${ STATE_DIR } /logs/deezer-artist-id-not-found.txt "
NotifyWebhook "ArtistError" \
" Update Musicbrainz Relationship Page: \
<https://musicbrainz.org/artist/${ lidarrArtistForeignArtistId } /edit> for ${ lidarrArtistName } with Deezer Artist Link"
2023-07-11 14:14:37 +02:00
fi
fi
fi
2024-11-26 22:01:19 +01:00
if [ " $skipTidal " = = "false" ] && [ -z " $tidalArtistUrl " ] ; then
log " TIDAL :: ERROR :: musicbrainz id: $lidarrArtistForeignArtistId is missing Tidal link, see: \
\" ${ STATE_DIR } /logs/tidal-artist-id-not-found.txt\" for more detail..."
touch " ${ STATE_DIR } /logs/tidal-artist-id-not-found.txt "
skipTidal = true
if grep " https://musicbrainz.org/artist/ $lidarrArtistForeignArtistId /edit " " ${ STATE_DIR } /logs/tidal-artist-id-not-found.txt " | read -r; then
sleep 0.01
else
echo " Update Musicbrainz Relationship Page: \
https://musicbrainz.org/artist/$lidarrArtistForeignArtistId /edit for \" ${ lidarrArtistName } \" with Tidal Artist Link" \
>> " ${ STATE_DIR } /logs/tidal-artist-id-not-found.txt "
NotifyWebhook "ArtistError" \
" Update Musicbrainz Relationship Page: \
<https://musicbrainz.org/artist/${ lidarrArtistForeignArtistId } /edit> for ${ lidarrArtistName } with Tidal Artist Link"
2023-07-11 14:14:37 +02:00
fi
fi
# Begin cosolidated search process
if [ " $audioLyricType " = = "both" ] ; then
endLoop = "2"
else
endLoop = "1"
fi
# Get Release Titles & Disambiguation
2024-11-26 22:01:19 +01:00
[ -f "/tmp/temp-release-list" ] \
&& rm /tmp/temp-release-list
for releaseId in $lidarrAlbumReleaseIds ; do
2023-07-11 14:14:37 +02:00
releaseTitle = $( echo " $lidarrAlbumData " | jq -r " .releases[] | select(.id== $releaseId ) | .title " )
releaseDisambiguation = $( echo " $lidarrAlbumData " | jq -r " .releases[] | select(.id== $releaseId ) | .disambiguation " )
if [ -z " $releaseDisambiguation " ] ; then
releaseDisambiguation = ""
else
releaseDisambiguation = " ( $releaseDisambiguation ) "
fi
2024-11-26 22:01:19 +01:00
echo " ${ releaseTitle } ${ releaseDisambiguation } " >> /tmp/temp-release-list
2023-07-11 14:14:37 +02:00
done
2024-11-26 22:01:19 +01:00
echo " $lidarrAlbumTitle " >> /tmp/temp-release-list
2023-07-11 14:14:37 +02:00
# Get Release Titles
OLDIFS = " $IFS "
IFS = $'\n'
2024-08-01 15:36:02 +02:00
if [ " $preferSpecialEditions " = = "true" ] ; then
2024-11-26 22:01:19 +01:00
lidarrReleaseTitles = $( < /tmp/temp-release-list awk '{ print length, $0 }' | sort -u -n -s -r | cut -d" " -f2-)
2024-08-01 15:36:02 +02:00
else
2024-11-26 22:01:19 +01:00
lidarrReleaseTitles = $( < /tmp/temp-release-list awk '{ print length, $0 }' | sort -u -n -s | cut -d" " -f2-)
2024-08-01 15:36:02 +02:00
fi
2024-11-26 22:01:19 +01:00
mapfile -t lidarrReleaseTitles < <( echo " $lidarrReleaseTitles " )
2023-07-11 14:14:37 +02:00
IFS = " $OLDIFS "
loopCount = 0
2024-11-26 22:01:19 +01:00
until false; do
loopCount = $(( loopCount + 1 ))
2023-07-11 14:14:37 +02:00
if [ " $loopCount " = = "1" ] ; then
# First loop is either explicit or clean depending on script settings
if [ " $audioLyricType " = = "both" ] || [ " $audioLyricType " = = "explicit" ] ; then
lyricFilter = "true"
else
lyricFilter = "false"
fi
else
# 2nd loop is always clean
lyricFilter = "false"
fi
2023-09-22 00:42:57 +02:00
lidarrDownloadImportNotfication = "false"
2023-07-11 14:14:37 +02:00
releaseProcessCount = 0
2024-11-26 22:01:19 +01:00
for title in " ${ !lidarrReleaseTitles[@] } " ; do
releaseProcessCount = $(( releaseProcessCount + 1 ))
2023-07-11 14:14:37 +02:00
lidarrReleaseTitle = " ${ lidarrReleaseTitles [ $title ] } "
lidarrAlbumReleaseTitleClean = $( echo " $lidarrReleaseTitle " | sed -e "s%[^[:alpha:][:digit:]]%%g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' )
2024-11-26 22:01:19 +01:00
lidarrAlbumReleaseTitleClean = " ${ lidarrAlbumReleaseTitleClean : 0 : 130 } "
2023-07-11 14:14:37 +02:00
lidarrAlbumReleaseTitleSearchClean = " $( echo " $lidarrReleaseTitle " | sed -e "s%[^[:alpha:][:digit:]]% %g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' ) "
lidarrAlbumReleaseTitleFirstWord = " $( echo " $lidarrReleaseTitle " | awk '{ print $1 }' ) "
lidarrAlbumReleaseTitleFirstWord = " ${ lidarrAlbumReleaseTitleFirstWord : 0 : 3 } "
albumTitleSearch = " $( jq -R -r @uri <<< " ${ lidarrAlbumReleaseTitleSearchClean } " ) "
#echo "Debugging :: $loopCount :: $releaseProcessCount :: $lidarrArtistForeignArtistId :: $lidarrReleaseTitle :: $lidarrAlbumReleasesMinTrackCount-$lidarrAlbumReleasesMaxTrackCount :: $lidarrAlbumReleaseTitleFirstWord :: $albumArtistNameSearch :: $albumTitleSearch"
2023-09-22 03:41:15 +02:00
2024-01-11 19:32:47 +01:00
2024-11-26 22:01:19 +01:00
if echo " $lidarrAlbumTitle " | grep -i "instrumental" | read -r; then
2024-01-11 21:15:36 +01:00
sleep 0.01
2024-11-26 22:01:19 +01:00
elif [ " $ignoreInstrumentalRelease " = = "true" ] && echo " $lidarrReleaseTitle " | grep -i "instrumental" | read -r ; then
logDl "Instrumental Release Found, Skipping..."
continue
2024-01-11 21:15:36 +01:00
fi
2024-01-11 19:32:47 +01:00
2023-07-11 14:14:37 +02:00
# Skip Various Artists album search that is not supported...
2024-11-26 22:01:19 +01:00
if [ " $lidarrArtistForeignArtistId " != "89ad4ac3-39f7-470e-963a-56509c546377" ] \
&& [ " $lidarrDownloadImportNotfication " = = "false" ] ; then
2023-07-11 14:14:37 +02:00
# Tidal Artist search
2024-11-26 22:01:19 +01:00
if [ " $dlClientSource " = = "both" ] || [ " $dlClientSource " = = "tidal" ] ; then
for tidalArtistId in $tidalArtistIds ; do
ArtistTidalSearch " $page :: $wantedAlbumListSource :: $processNumber of $wantedListAlbumTotal " " $tidalArtistId " " $lyricFilter "
sleep 0.01
done
2023-07-11 14:14:37 +02:00
fi
# Deezer artist search
2024-11-26 22:01:19 +01:00
if [ " $dlClientSource " = = "both" ] || [ " $dlClientSource " = = "deezer" ] ; then
for dId in " ${ !deezerArtistIds[@] } " ; do
deezerArtistId = " ${ deezerArtistIds [ $dId ] } "
ArtistDeezerSearch " $page :: $wantedAlbumListSource :: $processNumber of $wantedListAlbumTotal " " $deezerArtistId " " $lyricFilter "
sleep 0.01
done
2023-07-11 14:14:37 +02:00
fi
fi
2023-09-22 04:04:03 +02:00
#log "3 : $lidarrDownloadImportNotfication"
2023-07-11 14:14:37 +02:00
# Tidal fuzzy search
2023-09-22 00:42:57 +02:00
if [ " $lidarrDownloadImportNotfication " = = "false" ] ; then
if [ " $dlClientSource " = = "both" ] || [ " $dlClientSource " = = "tidal" ] ; then
FuzzyTidalSearch " $page :: $wantedAlbumListSource :: $processNumber of $wantedListAlbumTotal " " $lyricFilter "
sleep 0.01
fi
2023-07-11 14:14:37 +02:00
fi
2023-09-22 04:04:03 +02:00
#log "4 : $lidarrDownloadImportNotfication"
2023-07-11 14:14:37 +02:00
# Deezer fuzzy search
2023-09-22 00:42:57 +02:00
if [ " $lidarrDownloadImportNotfication " = = "false" ] ; then
if [ " $dlClientSource " = = "both" ] || [ " $dlClientSource " = = "deezer" ] ; then
FuzzyDeezerSearch " $page :: $wantedAlbumListSource :: $processNumber of $wantedListAlbumTotal " " $lyricFilter "
sleep 0.01
fi
2023-07-11 14:14:37 +02:00
fi
2023-09-22 00:42:57 +02:00
# End search if lidarr was successfully notified for import
if [ " $lidarrDownloadImportNotfication " = = "true" ] ; then
break
fi
2023-07-11 14:14:37 +02:00
done
2023-09-22 00:42:57 +02:00
# End search if lidarr was successfully notified for import
if [ " $lidarrDownloadImportNotfication " = = "true" ] ; then
break
fi
2023-07-11 14:14:37 +02:00
# Break after all operations are complete
if [ " $loopCount " = = " $endLoop " ] ; then
2024-11-26 22:01:19 +01:00
logDl "Album Not found"
2023-09-22 03:41:15 +02:00
if [ " $skipNotFoundLogCreation " = = "false" ] ; then
2024-11-26 22:01:19 +01:00
logDl "Marking Album as notfound"
if [ ! -f " ${ STATE_DIR } /extended/logs/notfound/ $wantedAlbumId -- $lidarrArtistForeignArtistId -- $lidarrAlbumForeignAlbumId " ] ; then
touch " ${ STATE_DIR } /extended/logs/notfound/ $wantedAlbumId -- $lidarrArtistForeignArtistId -- $lidarrAlbumForeignAlbumId "
2023-09-22 03:41:15 +02:00
fi
else
2024-11-26 22:01:19 +01:00
logDl "Skip marking album as not found because it's a new release for 7 days..."
2023-09-22 03:41:15 +02:00
fi
2023-07-11 14:14:37 +02:00
break
fi
done
2024-11-26 22:01:19 +01:00
logDl "Search Complete..."
2023-07-11 14:14:37 +02:00
done
}
GetDeezerAlbumInfo ( ) {
2024-11-26 22:01:19 +01:00
until false; do
logDl "Getting Album info..."
if [ ! -f " ${ STATE_DIR } /extended/cache/deezer/ $1 .json " ] ; then
curl -s " https://api.deezer.com/album/ $1 " -o " ${ STATE_DIR } /extended/cache/deezer/ $1 .json "
2023-07-11 14:14:37 +02:00
sleep $sleepTimer
fi
2024-11-26 22:01:19 +01:00
if [ -f " ${ STATE_DIR } /extended/cache/deezer/ $1 .json " ] ; then
if jq -e . >/dev/null 2>& 1 <<< " $( cat " ${ STATE_DIR } /extended/cache/deezer/ $1 .json " ) " ; then
2023-07-11 14:14:37 +02:00
log " $page :: $wantedAlbumListSource :: $processNumber of $wantedListAlbumTotal :: $lidarrArtistName :: $lidarrAlbumTitle :: Album info downloaded and verified... "
albumInfoVerified = true
break
else
log " $page :: $wantedAlbumListSource :: $processNumber of $wantedListAlbumTotal :: $lidarrArtistName :: $lidarrAlbumTitle :: Error getting album information "
2024-11-26 22:01:19 +01:00
if [ -f " ${ STATE_DIR } /extended/cache/deezer/ $1 .json " ] ; then
rm " ${ STATE_DIR } /extended/cache/deezer/ $1 .json "
2023-07-11 14:14:37 +02:00
fi
log " $page :: $wantedAlbumListSource :: $processNumber of $wantedListAlbumTotal :: $lidarrArtistName :: $lidarrAlbumTitle :: Retrying... "
fi
else
log " $page :: $wantedAlbumListSource :: $processNumber of $wantedListAlbumTotal :: $lidarrArtistName :: $lidarrAlbumTitle :: ERROR :: Download Failed "
fi
done
}
ArtistDeezerSearch ( ) {
# Required Inputs
# $1 Process ID
# $2 Deezer Artist ID
# $3 Lyric Type (true or false) - false == Clean, true == Explicit
# Get deezer artist album list
2024-11-26 22:01:19 +01:00
if [ ! -d " ${ STATE_DIR } /extended/cache/deezer " ] ; then
mkdir -p " ${ STATE_DIR } /extended/cache/deezer "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
if [ ! -f " ${ STATE_DIR } /extended/cache/deezer/ $2 -albums.json " ] ; then
getDeezerArtistAlbums = $( curl -s " https://api.deezer.com/artist/ $2 /albums?limit=1000 " > " ${ STATE_DIR } /extended/cache/deezer/ $2 -albums.json " )
2023-07-11 14:14:37 +02:00
sleep $sleepTimer
2024-11-26 22:01:19 +01:00
getDeezerArtistAlbumsCount = " $( jq -r .total " ${ STATE_DIR } /extended/cache/deezer/ $2 -albums.json " ) "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
[ " $getDeezerArtistAlbumsCount " = = "0" ] && return
2023-07-11 14:14:37 +02:00
if [ " $3 " = = "true" ] ; then
type = "Explicit"
else
type = "Clean"
fi
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
Searching $2 ... ( Track Count: $lidarrAlbumReleasesMinTrackCount -$lidarrAlbumReleasesMaxTrackCount ) ..."
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Deezer :: $type :: $lidarrReleaseTitle :: Filtering results by lyric type..."
deezerArtistAlbumsData = $( jq -r .data[ ] " ${ STATE_DIR } /extended/cache/deezer/ $2 -albums.json " )
deezerArtistAlbumsIds = $( echo " ${ deezerArtistAlbumsData } " | jq -r " select(.explicit_lyrics==\" $3 \") | .id " )
2023-07-11 14:14:37 +02:00
resultsCount = $( echo " $deezerArtistAlbumsIds " | wc -l)
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Deezer :: $type :: $lidarrReleaseTitle :: $resultsCount search results found"
for deezerAlbumID in $deezerArtistAlbumsIds ; do
2023-07-11 14:14:37 +02:00
deezerAlbumData = " $( echo " $deezerArtistAlbumsData " | jq -r " select(.id== $deezerAlbumID ) " ) "
deezerAlbumTitle = " $( echo " $deezerAlbumData " | jq -r ".title" ) "
2024-11-26 22:01:19 +01:00
deezerAlbumTitleClean = " $( echo " ${ deezerAlbumTitle } " | sed -e "s%[^[:alpha:][:digit:]]%%g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' ) "
deezerAlbumTitleClean = " ${ deezerAlbumTitleClean : 0 : 130 } "
2023-07-11 14:14:37 +02:00
GetDeezerAlbumInfo " $deezerAlbumID "
2024-11-26 22:01:19 +01:00
deezerAlbumData = " $( cat " ${ STATE_DIR } /extended/cache/deezer/ $deezerAlbumID .json " ) "
2023-07-11 14:14:37 +02:00
deezerAlbumTrackCount = " $( echo " $deezerAlbumData " | jq -r .nb_tracks) "
deezerAlbumExplicitLyrics = " $( echo " $deezerAlbumData " | jq -r .explicit_lyrics) "
downloadedReleaseDate = " $( echo " $deezerAlbumData " | jq -r .release_date) "
downloadedReleaseYear = " ${ downloadedReleaseDate : 0 : 4 } "
# Reject release if greater than the max track count
2024-11-26 22:01:19 +01:00
[ " $deezerAlbumTrackCount " -gt " $lidarrAlbumReleasesMaxTrackCount " ] && continue
2023-07-11 14:14:37 +02:00
# Reject release if less than the min track count
2024-11-26 22:01:19 +01:00
[ " $deezerAlbumTrackCount " -lt " $lidarrAlbumReleasesMinTrackCount " ] && continue
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $deezerAlbumTitleClean :: Checking for Match..."
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $deezerAlbumTitleClean :: Calculating Damerau-Levenshtein distance..."
diff = $( python -c " from editdistpy import damerau_osa; \
print( damerau_osa.distance( \" ${ lidarrAlbumReleaseTitleClean ,, } \" , \" ${ deezerAlbumTitleClean ,, } \" , $matchDistance ) ) " \
2>/dev/null
)
if [ " $diff " != "-1" ] ; then
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $deezerAlbumTitleClean :: Deezer MATCH Found :: Calculated Difference = $diff "
2023-07-11 14:14:37 +02:00
# Execute Download
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
Downloading $deezerAlbumTrackCount Tracks :: $deezerAlbumTitle ( $downloadedReleaseYear ) "
2023-07-11 14:14:37 +02:00
DownloadProcess " $deezerAlbumID " "DEEZER" " $downloadedReleaseYear " " $deezerAlbumTitle " " $deezerAlbumTrackCount "
2024-02-06 17:21:41 +01:00
else
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $deezerAlbumTitleClean :: \
Deezer Match Not Found :: Calculated Difference ( $diff ) greater than $matchDistance "
2023-07-11 14:14:37 +02:00
fi
2023-09-22 04:04:03 +02:00
# End search if lidarr was successfully notified for import
if [ " $lidarrDownloadImportNotfication " = = "true" ] ; then
break
fi
2023-09-22 00:42:57 +02:00
done
2023-07-11 14:14:37 +02:00
}
FuzzyDeezerSearch ( ) {
# Required Inputs
# $1 Process ID
2024-02-01 03:59:23 +01:00
# $2 Lyric Type (explicit = true, clean = false)
2023-07-11 14:14:37 +02:00
if [ " $2 " = = "true" ] ; then
type = "Explicit"
else
type = "Clean"
fi
2024-11-26 22:01:19 +01:00
[ ! -d " ${ STATE_DIR } /extended/cache/deezer " ] \
&& mkdir -p " ${ STATE_DIR } /extended/cache/deezer "
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
Searching... ( Track Count: $lidarrAlbumReleasesMinTrackCount -$lidarrAlbumReleasesMaxTrackCount ) "
2023-07-11 14:14:37 +02:00
deezerSearch = ""
if [ " $lidarrArtistForeignArtistId " = = "89ad4ac3-39f7-470e-963a-56509c546377" ] ; then
# Search without Artist for VA albums
deezerSearch = $( curl -s " https://api.deezer.com/search?q=album:%22 ${ albumTitleSearch } %22&strict=on&limit=20 " | jq -r ".data[]" )
else
# Search with Artist for non VA albums
deezerSearch = $( curl -s " https://api.deezer.com/search?q=artist:%22 ${ albumArtistNameSearch } %22%20album:%22 ${ albumTitleSearch } %22&strict=on&limit=20 " | jq -r ".data[]" )
fi
2024-11-26 22:01:19 +01:00
2023-07-11 14:14:37 +02:00
resultsCount = $( echo " $deezerSearch " | jq -r .album.id | sort -u | wc -l)
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Deezer :: $type :: $lidarrReleaseTitle :: $resultsCount search results found"
if [ -n " $deezerSearch " ] ; then
2023-07-11 14:14:37 +02:00
for deezerAlbumID in $( echo " $deezerSearch " | jq -r .album.id | sort -u) ; do
deezerAlbumData = " $( echo " $deezerSearch " | jq -r " .album | select(.id== $deezerAlbumID ) " ) "
deezerAlbumTitle = " $( echo " $deezerAlbumData " | jq -r ".title" ) "
deezerAlbumTitle = " $( echo " $deezerAlbumTitle " | head -n1) "
deezerAlbumTitleClean = " $( echo " $deezerAlbumTitle " | sed -e "s%[^[:alpha:][:digit:]]%%g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' ) "
2024-01-11 12:25:50 +01:00
deezerAlbumTitleClean = " ${ deezerAlbumTitleClean : 0 : 130 } "
2023-07-11 14:14:37 +02:00
GetDeezerAlbumInfo " ${ deezerAlbumID } "
2024-11-26 22:01:19 +01:00
deezerAlbumData = " $( cat " ${ STATE_DIR } /extended/cache/deezer/ $deezerAlbumID .json " ) "
2023-07-11 14:14:37 +02:00
deezerAlbumTrackCount = " $( echo " $deezerAlbumData " | jq -r .nb_tracks) "
deezerAlbumExplicitLyrics = " $( echo " $deezerAlbumData " | jq -r .explicit_lyrics) "
downloadedReleaseDate = " $( echo " $deezerAlbumData " | jq -r .release_date) "
downloadedReleaseYear = " ${ downloadedReleaseDate : 0 : 4 } "
2024-11-26 22:01:19 +01:00
[ " $deezerAlbumExplicitLyrics " != " $2 " ] && continue
2023-07-11 14:14:37 +02:00
# Reject release if greater than the max track count
2024-11-26 22:01:19 +01:00
[ " $deezerAlbumTrackCount " -gt " $lidarrAlbumReleasesMaxTrackCount " ] && continue
2023-07-11 14:14:37 +02:00
# Reject release if less than the min track count
2024-11-26 22:01:19 +01:00
[ " $deezerAlbumTrackCount " -lt " $lidarrAlbumReleasesMinTrackCount " ] && continue
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $deezerAlbumTitleClean :: Checking for Match..."
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $deezerAlbumTitleClean :: Calculating Damerau-Levenshtein distance..."
diff = $( python -c " from editdistpy import damerau_osa; \
print( damerau_osa.distance( \" ${ lidarrAlbumReleaseTitleClean ,, } \" , \" ${ deezerAlbumTitleClean ,, } \" , $matchDistance ) ) " \
2>/dev/null
)
if [ " $diff " != "-1" ] ; then
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $deezerAlbumTitleClean :: Deezer MATCH Found :: Calculated Difference = $diff "
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
Downloading $deezerAlbumTrackCount Tracks :: $deezerAlbumTitle ( $downloadedReleaseYear ) "
2023-07-11 14:14:37 +02:00
DownloadProcess " $deezerAlbumID " "DEEZER" " $downloadedReleaseYear " " $deezerAlbumTitle " " $deezerAlbumTrackCount "
2024-02-06 17:21:41 +01:00
else
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $deezerAlbumTitleClean :: \
Deezer Match Not Found :: Calculated Difference ( $diff ) greater than $matchDistance "
2023-07-11 14:14:37 +02:00
fi
2023-09-22 04:04:03 +02:00
# End search if lidarr was successfully notified for import
if [ " $lidarrDownloadImportNotfication " = = "true" ] ; then
break
fi
2023-07-11 14:14:37 +02:00
done
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
ERROR :: Results found, but none matching search criteria..."
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Deezer :: $type :: $lidarrReleaseTitle :: \
ERROR :: No results found via Fuzzy Search..."
2023-07-11 14:14:37 +02:00
fi
}
ArtistTidalSearch ( ) {
# Required Inputs
# $1 Process ID
# $2 Tidal Artist ID
# $3 Lyric Type (true or false) - false = Clean, true = Explicit
# Get tidal artist album list
2024-11-26 22:01:19 +01:00
if [ ! -f " ${ STATE_DIR } /extended/cache/tidal/ $2 -albums.json " ] ; then
curl -s " https://api.tidal.com/v1/artists/ $2 /albums?limit=10000&countryCode= $tidalCountryCode &filter=ALL " -H 'x-tidal-token: CzET4vdadNUFQ5JU' \
> " ${ STATE_DIR } /extended/cache/tidal/ $2 -albums.json "
2023-07-11 14:14:37 +02:00
sleep $sleepTimer
fi
2024-11-26 22:01:19 +01:00
if [ ! -f " ${ STATE_DIR } /extended/cache/tidal/ $2 -albums.json " ] ; then
2023-07-11 14:14:37 +02:00
return
fi
if [ " $3 " = = "true" ] ; then
type = "Explicit"
else
type = "Clean"
fi
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
Searching $2 ... ( Track Count: $lidarrAlbumReleasesMinTrackCount -$lidarrAlbumReleasesMaxTrackCount ) ..."
tidalArtistAlbumsData = $( jq -r " .items | sort_by(.numberOfTracks) | sort_by(.explicit) | \
reverse | .[ ] | select ( ( .numberOfTracks <= $lidarrAlbumReleasesMaxTrackCount ) and .numberOfTracks >= $lidarrAlbumReleasesMinTrackCount ) " \
" ${ STATE_DIR } /extended/cache/tidal/ $2 -albums.json " )
2023-07-11 14:14:37 +02:00
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Tidal :: $type :: $lidarrReleaseTitle :: Filtering results by lyric type, track count"
tidalArtistAlbumsIds = $( echo " ${ tidalArtistAlbumsData } " | jq -r " select(.explicit==\" $3 \") | .id " )
2023-07-11 14:14:37 +02:00
if [ -z " $tidalArtistAlbumsIds " ] ; then
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
ERROR :: No search results found..."
2023-07-11 14:14:37 +02:00
return
fi
searchResultCount = $( echo " $tidalArtistAlbumsIds " | wc -l)
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
$searchResultCount search results found"
for tidalArtistAlbumId in $tidalArtistAlbumsIds ; do
tidalArtistAlbumData = $( echo " $tidalArtistAlbumsData " | jq -r " select(.id==\" $tidalArtistAlbumId \") " )
downloadedAlbumTitle = " $( echo " ${ tidalArtistAlbumData } " | jq -r .title) "
tidalAlbumTitleClean = $( echo " ${ downloadedAlbumTitle } " | sed -e "s%[^[:alpha:][:digit:]]%%g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' )
2024-01-11 12:25:50 +01:00
tidalAlbumTitleClean = " ${ tidalAlbumTitleClean : 0 : 130 } "
2024-11-26 22:01:19 +01:00
downloadedReleaseDate = " $( echo " ${ tidalArtistAlbumData } " | jq -r .releaseDate) "
2023-07-11 14:14:37 +02:00
if [ " $downloadedReleaseDate " = = "null" ] ; then
2024-11-26 22:01:19 +01:00
downloadedReleaseDate = $( echo " $tidalArtistAlbumData " | jq -r '.streamStartDate' )
2023-07-11 14:14:37 +02:00
fi
downloadedReleaseYear = " ${ downloadedReleaseDate : 0 : 4 } "
downloadedTrackCount = $( echo " $tidalArtistAlbumData " | jq -r .numberOfTracks)
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $tidalAlbumTitleClean :: Checking for Match..."
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $tidalAlbumTitleClean :: Calculating Damerau-Levenshtein distance..."
diff = $( python -c " from editdistpy import damerau_osa; \
print( damerau_osa.distance( \" ${ lidarrAlbumReleaseTitleClean ,, } \" , \" ${ deezerAlbumTitleClean ,, } \" , $matchDistance ) ) " \
2>/dev/null
)
if [ " $diff " != "-1" ] ; then
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $tidalAlbumTitleClean :: \
Tidal MATCH Found :: Calculated Difference = $diff "
2023-07-11 14:14:37 +02:00
# Execute Download
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
Downloading $downloadedTrackCount Tracks :: $downloadedAlbumTitle ( $downloadedReleaseYear ) "
2023-07-11 14:14:37 +02:00
DownloadProcess " $tidalArtistAlbumId " "TIDAL" " $downloadedReleaseYear " " $downloadedAlbumTitle " " $downloadedTrackCount "
2023-09-22 04:04:03 +02:00
# End search if lidarr was successfully notified for import
2024-11-26 22:01:19 +01:00
[ " $lidarrDownloadImportNotfication " = = "true" ] && break
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Artist Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $tidalAlbumTitleClean :: \
Tidal Match Not Found :: Calculated Difference ( $diff ) greater than $matchDistance "
2023-07-11 14:14:37 +02:00
fi
done
}
FuzzyTidalSearch ( ) {
# Required Inputs
# $1 Process ID
# $2 Lyric Type (explicit = true, clean = false)
if [ " $2 " = = "true" ] ; then
type = "Explicit"
else
type = "Clean"
fi
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
Searching... ( Track Count: $lidarrAlbumReleasesMinTrackCount -$lidarrAlbumReleasesMaxTrackCount ) ..."
2023-07-11 14:14:37 +02:00
if [ " $lidarrArtistForeignArtistId " = = "89ad4ac3-39f7-470e-963a-56509c546377" ] ; then
# Search without Artist for VA albums
2024-11-26 22:01:19 +01:00
tidalSearch = $( curl -s " https://api.tidal.com/v1/search/albums?query= ${ albumTitleSearch } &countryCode= ${ tidalCountryCode } &limit=20 " \
-H 'x-tidal-token: CzET4vdadNUFQ5JU' \
| jq -r " .items | sort_by(.numberOfTracks) \
| sort_by( .explicit) | reverse | .[ ] | select ( .explicit= = \" $2 \" ) \
| select ( ( .numberOfTracks <= $lidarrAlbumReleasesMaxTrackCount ) and .numberOfTracks >= $lidarrAlbumReleasesMinTrackCount ) " )
2023-07-11 14:14:37 +02:00
else
# Search with Artist for non VA albums
2024-11-26 22:01:19 +01:00
tidalSearch = $( curl -s \
" https://api.tidal.com/v1/search/albums?query= ${ albumArtistNameSearch } %20 ${ albumTitleSearch } &countryCode= ${ tidalCountryCode } &limit=20 " \
-H 'x-tidal-token: CzET4vdadNUFQ5JU' \
| jq -r " .items | sort_by(.numberOfTracks) \
| sort_by( .explicit) | reverse | .[ ] | select ( .explicit= = \" $2 \" ) \
| select ( ( .numberOfTracks <= $lidarrAlbumReleasesMaxTrackCount ) and .numberOfTracks >= $lidarrAlbumReleasesMinTrackCount ) " )
2023-07-11 14:14:37 +02:00
fi
sleep $sleepTimer
2023-09-07 13:41:57 +02:00
tidalSearch = $( echo " $tidalSearch " | jq -r )
2023-07-11 14:14:37 +02:00
searchResultCount = $( echo " $tidalSearch " | jq -r ".id" | sort -u | wc -l)
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Tidal :: $type :: $lidarrReleaseTitle :: $searchResultCount search results found"
if [ -n " $tidalSearch " ] ; then
2023-07-11 14:14:37 +02:00
for tidalAlbumID in $( echo " $tidalSearch " | jq -r .id | sort -u) ; do
tidalAlbumData = " $( echo " $tidalSearch " | jq -r " select(.id== $tidalAlbumID ) " ) "
tidalAlbumTitle = $( echo " $tidalAlbumData " | jq -r .title)
2024-11-26 22:01:19 +01:00
tidalAlbumTitleClean = $( echo " ${ tidalAlbumTitle } " | sed -e "s%[^[:alpha:][:digit:]]%%g" -e "s/ */ /g" | sed 's/^[.]*//' | sed 's/[.]*$//g' | sed 's/^ *//g' | sed 's/ *$//g' )
2024-01-11 12:25:50 +01:00
tidalAlbumTitleClean = " ${ tidalAlbumTitleClean : 0 : 130 } "
2024-11-26 22:01:19 +01:00
downloadedReleaseDate = " $( echo " ${ tidalAlbumData } " | jq -r .releaseDate) "
2023-07-11 14:14:37 +02:00
if [ " $downloadedReleaseDate " = = "null" ] ; then
2024-11-26 22:01:19 +01:00
downloadedReleaseDate = $( echo " $tidalAlbumData " | jq -r '.streamStartDate' )
2023-07-11 14:14:37 +02:00
fi
downloadedReleaseYear = " ${ downloadedReleaseDate : 0 : 4 } "
downloadedTrackCount = $( echo " $tidalAlbumData " | jq -r .numberOfTracks)
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $tidalAlbumTitleClean :: Checking for Match..."
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $tidalAlbumTitleClean :: Calculating Damerau-Levenshtein distance..."
diff = $( python -c " from editdistpy import damerau_osa; \
print( damerau_osa.distance( \" ${ lidarrAlbumReleaseTitleClean ,, } \" , \" ${ deezerAlbumTitleClean ,, } \" , $matchDistance ) ) " \
2>/dev/null
)
if [ " $diff " != "-1" ] ; then
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $tidalAlbumTitleClean :: \
Tidal MATCH Found :: Calculated Difference = $diff "
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
Downloading $downloadedTrackCount Tracks :: $tidalAlbumTitle ( $downloadedReleaseYear ) "
2023-07-11 14:14:37 +02:00
DownloadProcess " $tidalAlbumID " "TIDAL" " $downloadedReleaseYear " " $tidalAlbumTitle " " $downloadedTrackCount "
else
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
$lidarrAlbumReleaseTitleClean vs $tidalAlbumTitleClean :: \
Tidal Match Not Found :: Calculated Difference ( $diff ) greater than $matchDistance "
2023-07-11 14:14:37 +02:00
fi
2023-09-22 04:04:03 +02:00
# End search if lidarr was successfully notified for import
2024-11-26 22:01:19 +01:00
[ " $lidarrDownloadImportNotfication " = = "true" ] && break
2023-07-11 14:14:37 +02:00
done
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Tidal :: $type :: $lidarrReleaseTitle :: \
ERROR :: Albums found, but none matching search criteria..."
2023-07-11 14:14:37 +02:00
else
2024-11-26 22:01:19 +01:00
log " $1 :: $lidarrArtistName :: $lidarrAlbumTitle :: $lidarrAlbumType :: \
Fuzzy Search :: Tidal :: $type :: $lidarrReleaseTitle :: ERROR :: No results found..."
2023-07-11 14:14:37 +02:00
fi
}
LidarrTaskStatusCheck ( ) {
alerted = no
until false
do
2023-07-11 15:41:58 +02:00
taskCount = $( curl -s " $arrUrl /api/v1/command?apikey= ${ arrApiKey } " | jq -r '.[] | select(.status=="started") | .name' | wc -l)
2023-07-11 14:14:37 +02:00
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 2
else
break
fi
done
}
LidarrMissingAlbumSearch ( ) {
log "Begin searching for missing artist albums via Lidarr Indexers..."
2024-11-26 22:01:19 +01:00
lidarrArtistIds = $( echo " $lidarrMissingAlbumArtistsData " | jq -r .id)
2023-07-11 14:14:37 +02:00
lidarrArtistIdsCount = $( echo " $lidarrArtistIds " | wc -l)
processCount = 0
2024-11-26 22:01:19 +01:00
for lidarrArtistId in $lidarrArtistIds ; do
processCount = $(( processCount + 1 ))
lidarrArtistData = $( echo " $lidarrMissingAlbumArtistsData " | jq -r " select(.id== $lidarrArtistId ) " )
lidarrArtistName = $( echo " $lidarrArtistData " | jq -r .artistName)
lidarrArtistMusicbrainzId = $( echo " $lidarrArtistData " | jq -r .foreignArtistId)
if [ -d " ${ STATE_DIR } /extended/logs/searched/lidarr/artist " ] ; then
if [ -f " ${ STATE_DIR } /extended/logs/searched/lidarr/artist/ $lidarrArtistMusicbrainzId " ] ; then
log " $processCount of $lidarrArtistIdsCount :: \
Previously Notified Lidarr to search for \" $lidarrArtistName \" :: Skipping..."
2023-07-11 14:14:37 +02:00
continue
fi
fi
log " $processCount of $lidarrArtistIdsCount :: Notified Lidarr to search for \" $lidarrArtistName \" "
2024-11-26 22:01:19 +01:00
startLidarrArtistSearch = $( curl -s " $arrUrl /api/v1/command " -X POST \
-H "Content-Type: application/json" -H " X-Api-Key: $arrApiKey " \
--data-raw " {\"name\":\"ArtistSearch\",\"artistId\": $lidarrArtistId } " )
if [ ! -d " ${ STATE_DIR } /extended/logs/searched/lidarr/artist " ] ; then
mkdir -p " ${ STATE_DIR } /extended/logs/searched/lidarr/artist "
2023-07-11 14:14:37 +02:00
fi
2024-11-26 22:01:19 +01:00
touch " ${ STATE_DIR } /extended/logs/searched/lidarr/artist/ $lidarrArtistMusicbrainzId "
2023-07-11 14:14:37 +02:00
done
}
audioFlacVerification ( ) {
# Test Flac File for errors
# $1 File for verification
verifiedFlacFile = ""
verifiedFlacFile = $( flac --totally-silent -t " $1 " ; echo $? )
}
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
}
AudioProcess ( ) {
Configuration
LidarrRootFolderCheck
DownloadFormat
if [ " $dlClientSource " = = "deezer" ] || [ " $dlClientSource " = = "both" ] ; then
DeemixClientSetup
fi
if [ " $dlClientSource " = = "tidal" ] || [ " $dlClientSource " = = "both" ] ; then
TidalClientSetup
fi
LidarrTaskStatusCheck
# Get artist list for LidarrMissingAlbumSearch process, to prevent searching for artists that will not be processed by the script
2023-07-11 15:41:58 +02:00
lidarrMissingAlbumArtistsData = $( wget --timeout= 0 -q -O - " $arrUrl /api/v1/artist?apikey= $arrApiKey " | jq -r .[ ] )
2023-07-11 14:14:37 +02:00
if [ " $dlClientSource " = = "deezer" ] || [ " $dlClientSource " = = "tidal" ] || [ " $dlClientSource " = = "both" ] ; then
GetMissingCutOffList
else
log "ERROR :: No valid dlClientSource set"
log "ERROR :: Expected configuration :: deezer or tidal or both"
log " ERROR :: dlClientSource set as: \" $dlClientSource \" "
fi
if [ " $addDeezerTopArtists " = = "true" ] || [ " $addDeezerTopAlbumArtists " = = "true" ] || [ " $addDeezerTopTrackArtists " = = "true" ] || [ " $addRelatedArtists " = = "true" ] ; then
LidarrTaskStatusCheck
LidarrMissingAlbumSearch
fi
log "Script end..."
}
2023-07-12 16:01:00 +02:00
log "Starting Script...."
2023-07-11 14:14:37 +02:00
for ( ( ; ; ) ) ; do
2024-11-26 22:01:19 +01:00
( ( i++ ) ) || true
verifyConfig
getArrAppInfo " ${ STATE_DIR } "
2023-07-12 16:01:00 +02:00
verifyApiAccess
2023-07-11 14:14:37 +02:00
AudioProcess
2023-07-15 16:22:25 +02:00
log " Script sleeping for $audioScriptInterval ... "
2024-11-26 22:01:19 +01:00
sleep " $audioScriptInterval "
2023-07-11 14:14:37 +02:00
done
2023-08-16 14:40:22 +02:00
exit