Compare commits

..

12 commits
stable ... dev

5 changed files with 194 additions and 132 deletions

View file

@ -11,7 +11,7 @@
- Create install scripts/guides (WIP) - Create install scripts/guides (WIP)
- Migrate from Bash to a POSIX-compliant shell - Migrate from Bash to a POSIX-compliant shell
- Add Cover, and other metadata to vorbis tag (Almost done) - Add Cover, and other metadata to vorbis tag (Almost done)
- Lyrics download (WIP) - Lyrics download (Almost done)
- Implement search & download for playlists, albums, and artists (WIP) - Implement search & download for playlists, albums, and artists (WIP)
- Support downloading multiple search results - Support downloading multiple search results
- Allow users to choose audio quality (currently defaults to LOSSLESS) - Allow users to choose audio quality (currently defaults to LOSSLESS)

View file

@ -1,8 +1,8 @@
# Maintainer: Medvidek77 <medvidek77@tuta.io> # Maintainer: Medvidek77 <medvidek77@tuta.io>
pkgname=tidler pkgname=tidler
pkgver=0.3.0 pkgver=0.3.1
pkgrel=3 pkgrel=1
pkgdesc="Tidal music downloader based on the hifi-tui API" pkgdesc="Tidal music downloader based on the hifi-tui API"
arch=('any') arch=('any')
url="https://git.medvidek77.tech/Medvidek77/tidler" url="https://git.medvidek77.tech/Medvidek77/tidler"

View file

@ -1,8 +1,8 @@
# Maintainer: Medvidek77 <medvidek77@tuta.io> # Maintainer: Medvidek77 <medvidek77@tuta.io>
pkgname=tidler pkgname=tidler
pkgver=0.3.0 pkgver=0.3.2-beta2
pkgrel=3 pkgrel=1
pkgdesc="Tidal music downloader based on the hifi-tui API" pkgdesc="Tidal music downloader based on the hifi-tui API"
arch=('any') arch=('any')
url="https://git.medvidek77.tech/Medvidek77/tidler" url="https://git.medvidek77.tech/Medvidek77/tidler"

View file

@ -1,55 +1,56 @@
#!/bin/bash #!/usr/bin/env bash
. tidler.conf # Load ENVs from config file . tidler.conf # Load ENVs from config file
version="0.3.0" version="0.3.2-beta2"
if [ -n "$PROXY_URL" ]; then if [ -n "$PROXY_URL" ]; then
proxy_url="$PROXY_URL" proxy_url="$PROXY_URL"
else else
proxy_url="https://hifi-04ed2aaea09a.herokuapp.com" # Default value proxy_url="https://hifi-04ed2aaea09a.herokuapp.com" # Default value
fi fi
if [ -n "$QUALITY" ]; then if [ -n "$QUALITY" ]; then
if [ "$QUALITY" = "LOSSLESS" -o "$QUALITY" = "HI_RES" ]; then if [ "$QUALITY" = "LOSSLESS" -o "$QUALITY" = "HI_RES" ]; then
quality="$QUALITY" quality="$QUALITY"
else else
echo "Bad QUALITY option. Only allowed are \"LOSSLESS\", \"HI_RES\"." echo "Bad QUALITY option. Only allowed are \"LOSSLESS\", \"HI_RES\"."
echo "Using default value..." echo "Using default value..."
quality="LOSSLESS" # Default value quality="LOSSLESS" # Default value
fi fi
else else
quality="LOSSLESS" # Default value quality="LOSSLESS" # Default value
fi fi
if [ -n "$COVER_RESOLUTION" ]; then if [ -n "$COVER_RESOLUTION" ]; then
if [ "$COVER_RESOLUTION" = "1280" -o "$COVER_RESOLUTION" = "640" -o "$COVER_RESOLUTION" = "80" ]; then if [ "$COVER_RESOLUTION" = "1280" -o "$COVER_RESOLUTION" = "640" -o "$COVER_RESOLUTION" = "80" ]; then
cover_resolution="$COVER_RESOLUTION" cover_resolution="$COVER_RESOLUTION"
else else
echo "Bad COVER_RESOLUTION option. Only allowed are \"1280\", \"640\", \"80\"." echo "Bad COVER_RESOLUTION option. Only allowed are \"1280\", \"640\", \"80\"."
echo "Using default value..." echo "Using default value..."
cover_resolution="1280" # Default value cover_resolution="1280" # Default value
fi fi
else else
cover_resolution="1280" # Default value cover_resolution="1280" # Default value
fi fi
if [ -n "$MAX_ATTEMPTS" ]; then if [ -n "$MAX_ATTEMPTS" ]; then
if [ "$MAX_ATTEMPTS" -ge 1 -a "$MAX_ATTEMPTS" -le 100 ]; then if [ "$MAX_ATTEMPTS" -ge 1 -a "$MAX_ATTEMPTS" -le 100 ]; then
max_attempts="$MAX_ATTEMPTS" max_attempts="$MAX_ATTEMPTS"
else else
echo "Bad MAX_ATTEMPTS option. Allowed are numbers from 1 to 100." echo "Bad MAX_ATTEMPTS option. Allowed are numbers from 1 to 100."
echo "Using default value..." echo "Using default value..."
max_attempts="10" # Default value max_attempts="10" # Default value
fi fi
else else
max_attempts="10" # Default value max_attempts="10" # Default value
fi fi
downloadTrack() { downloadTrack() {
if [ "$#" -ge 1 ]; then if [ "$#" -ge 1 ]; then
echo "Downloading track with ID: $1" echo "Downloading track with ID: $1"
@ -59,14 +60,10 @@ downloadTrack() {
read -r id read -r id
fi fi
if [ "$#" -ge 2 ]; then
album_dir="$2"
else
album_dir=""
fi
attempt_num=1 attempt_num=1
success=false success=false
lrc_success=false
while [ $attempt_num -le $max_attempts ]; do while [ $attempt_num -le $max_attempts ]; do
json_data=$(curl -# "$proxy_url/track/?id=$id&quality=$quality") json_data=$(curl -# "$proxy_url/track/?id=$id&quality=$quality")
@ -87,11 +84,32 @@ downloadTrack() {
cover_data=$(curl -# "$proxy_url/cover/?id=$id") cover_data=$(curl -# "$proxy_url/cover/?id=$id")
cover_url=$(echo "$cover_data" | jq -r '.[]["1280"] // empty') cover_url=$(echo "$cover_data" | jq -r '.[]["1280"] // empty')
if [ -n "$cover_url" ]; then
track_number=$(echo "$json_data" | jq -r '.[0].trackNumber') if [ -n "$cover_url" ]; then
filename="$track_name.flac" date_data=$(echo "$json_data" | jq -r '.[0].streamStartDate // empty' )
cover_name="cover.png" date=$(expr substr "$date_data" 1 10)
success=true year=$(expr substr "$date_data" 1 4)
if [ -n "$year" ]; then
track_number=$(echo "$json_data" | jq -r '.[0].trackNumber')
filename="$track_name.flac"
cover_name="tidler_temp_cover_$track_name.png"
success=true
lyrics_data=$(curl -# "$proxy_url/lyrics/?id=$id")
if [ $? -eq 0 ]; then
timed_lyrics=$(echo "$lyrics_data" | jq -r '.[0].subtitles')
if [ -n "$timed_lyrics" ]; then
lrc_success=true
elif [ "$timed_lyrics" == "null" ]; then
echo "Lyrics not found"
fi
fi
fi
break break
fi fi
fi fi
@ -100,51 +118,58 @@ downloadTrack() {
fi fi
fi fi
if [ "$success" = false ]; then if [ "$success" = false ]; then
echo "Attempt $attempt_num failed. Retrying..." echo "Attempt $attempt_num failed. Retrying..."
((attempt_num++)) ((attempt_num++))
sleep "1.$(tr -cd 0-9 </dev/urandom | head -c 5)" sleep "1.$(tr -cd 0-9 < /dev/urandom | head -c 5)"
fi fi
done done
if [ "$success" = false ]; then if [ "$success" = false ]; then
echo "Failed to download after $max_attempts attempts." echo "Failed to download after $max_attempts attempts."
exit 1 exit 1
fi fi
if [ -n "$DOWNLOADS_DIR" ]; then if [ -n "$DOWNLOADS_DIR" ]; then
download_dir="$DOWNLOADS_DIR" download_dir="$DOWNLOADS_DIR"
else else
echo "Using current path..."
download_dir="$(pwd)" download_dir="$(pwd)"
fi fi
if [ -z "$album_dir" ]; then
final_path="$download_dir" final_path="$download_dir/$artist_name/$album_name"
else
final_path="$download_dir/$album_dir"
fi
mkdir -p "$final_path" mkdir -p "$final_path"
curl -# "$url" -o "$final_path/$filename" curl -# "$url" -o "$final_path/$filename"
curl -# "$cover_url" -o "$final_path/$cover_name" curl -# "$cover_url" -o "/tmp/$cover_name"
# Metadata
metaflac \ metaflac \
--set-tag="NAME=$track_name" \ --set-tag="NAME=$track_name" \
--set-tag="ARTIST=$artist_name" \ --set-tag="ARTIST=$artist_name" \
--set-tag="ALBUM=$album_name" \ --set-tag="ALBUM=$album_name" \
--set-tag="TRACKNUMBER=$track_number" \ --set-tag="TRACKNUMBER=$track_number" \
--import-picture-from="$final_path/$cover_name" \ ${lrc_success:+--set-tag="LYRICS=$timed_lyrics"} \
--set-tag="DATE=$date" \
--set-tag="YEAR=$year" \
--import-picture-from="/tmp/$cover_name" \
"$final_path/$filename" "$final_path/$filename"
rm "/tmp/$cover_name"
} }
searchTrack() { searchTrack() {
if [ "$#" -ge 1 ]; then if [ "$#" -ge 1 ]; then
track_name="$1" track_name="$1"
else else
echo "Enter track name:" echo "Enter track name:"
read -r track_name read -r track_name
fi fi
track_name=$(echo "$track_name" | sed 's/ /%20/g') track_name=$(echo "$track_name" | sed 's/ /%20/g')
tracks=$(curl -# "$proxy_url/search/?s=$track_name" | jq -r '.items[] | "\(.id) - \(.title) by \(.artist.name)"') tracks=$(curl -# "$proxy_url/search/?s=$track_name" | jq -r '.items[] | "\(.id) - \(.title) by \(.artist.name)"')
@ -157,19 +182,27 @@ searchTrack() {
if [ "${#tracks_list[@]}" -eq 1 ]; then if [ "${#tracks_list[@]}" -eq 1 ]; then
echo "No tracks found :(" echo "No tracks found :("
exit 1 exit 1
fi else
i=0
while [ "$i" -lt "${#tracks_list[@]}" ]; do
echo "$((i + 1))) ${tracks_list["$i"]}"
i=$(( i + 1 ))
done
read -a inp
echo "${inp[0]}"
i=0
while [ "$i" -lt "${#inp[@]}" ]; do
inp2=$(("${inp[i]}" - 1))
if [ "$inp2" -ge 0 ] && [ "$inp2" -lt "${#tracks_list[@]}" ]; then
track_id=$(echo "${tracks_list["$inp2"]}" | awk -F ' - ' '{print $1}')
downloadTrack "$track_id"
else
echo "Invalid selection. Please try again."
PS3="Please select a track: " fi
select t in "${tracks_list[@]}"; do i=$(( i + 1 ))
if [ -n "$t" ]; then done
track_id=$(echo "$t" | awk -F ' - ' '{print $1}') fi
echo "You selected: $t"
downloadTrack "$track_id"
break
else
echo "Invalid selection. Please try again."
fi
done
} }
@ -244,18 +277,27 @@ searchAlbum() {
((attempt_num++)) ((attempt_num++))
sleep "1.$(tr -cd 0-9 </dev/urandom | head -c 5)" sleep "1.$(tr -cd 0-9 </dev/urandom | head -c 5)"
else else
PS3="Please select an album: " i=0
select t in "${albums_list[@]}"; do while [ "$i" -lt "${#albums_list[@]}" ]; do
if [ -n "$t" ]; then echo "$((i + 1))) ${albums_list["$i"]}"
album_id=$(echo "$t" | awk -F ': ' '{print $1}')
echo "You selected: $t" i=$(( i + 1 ))
downloadAlbum "$album_id"
success=true
break
else
echo "Invalid selection. Please try again."
fi
done done
read -a inp
echo "${inp[0]}"
i=0
while [ "$i" -lt "${#inp[@]}" ]; do
inp2=$(("${inp[i]}" - 1))
if [ "$inp2" -ge 0 ] && [ "$inp2" -lt "${#albums_list[@]}" ]; then
album_id=$(echo "${albums_list["$inp2"]}" | awk -F ': ' '{print $1}')
downloadAlbum "$album_id"
else
echo "Invalid selection. Please try again."
fi
i=$(( i + 1 ))
done
success=true
if [ "$success" = true ]; then if [ "$success" = true ]; then
break break
fi fi
@ -268,57 +310,77 @@ searchAlbum() {
fi fi
} }
#searchArtist() {
#}
#downloadArtist() {
#}
if [ "$1" = "search" ]; then if [ "$1" = "search" ]; then
if [ "$#" -ge 2 ]; then if [ "$#" -ge 2 ]; then
shift shift
jsw="$*" jsw="$*"
searchTrack "$jsw" searchTrack "$jsw"
else else
searchTrack searchTrack
fi fi
elif [ "$1" = "download" ]; then elif [ "$1" = "download" ]; then
if [ "$#" -ge 2 ]; then if [ "$#" -ge 2 ]; then
downloadTrack "$2" downloadTrack "$2"
else else
downloadTrack downloadTrack
fi fi
elif [ "$1" = "album" ]; then elif [ "$1" = "album" ]; then
if [ "$#" -ge 2 ]; then if [ "$#" -ge 2 ]; then
shift shift
jsw="$*" jsw="$*"
searchAlbum "$jsw" searchAlbum "$jsw"
else else
searchAlbum searchAlbum
fi fi
elif [ "$1" == "version" ]; then elif [ "$1" == "version" ]; then
echo "TiDLer $version by Medvidek77" echo "TiDLer $version by Medvidek77"
elif [ "$1" = "help" ]; then elif [ "$1" = "help" ]; then
echo "<MODE>" echo "<MODE>"
echo "" echo ""
echo "If a valid parameter is provided, the corresponding function executes. Otherwise, TiDLer enters INTERACTIVE mode!" echo "If a valid parameter is provided, the corresponding function executes. Otherwise, TiDLer enters INTERACTIVE mode!"
echo "" echo ""
echo "<COMMANDS>" echo "<COMMANDS>"
echo "" echo ""
echo "search {track_name}-optional -> search any song" echo "search {track_name}-optional -> search any song"
echo "" echo ""
echo "download {song_id}-optional -> download any song" echo "download {song_id}-optional -> download any song"
echo "" echo ""
echo "album {album_name}-optional -> search and download any album" echo "album {album_name}-optional -> search and download any album"
echo "" echo ""
echo "version -> print TiDLer version" echo "version -> print TiDLer version"
echo "" echo ""
echo "help -> print this message and exit" echo "help -> print this message and exit"
else else
echo "### Choose function! (Enter number) ###" echo "### Choose function! (Enter number) ###"
echo "" echo ""
echo "1. Download single track with ID" echo "1. Download single track with ID"
echo "" echo ""
echo "2. Search single track with text" echo "2. Search single track with text"
echo "" echo ""
echo "3. Search and download whole album with text" echo "3. Search and download whole album with text"
read option
read option
if [ "$option" -eq 1 ]; then
downloadTrack
elif [ "$option" -eq 2 ]; then
searchTrack
elif [ "$option" -eq 3 ]; then
searchAlbum
fi
fi
if [ "$option" -eq 1 ]; then if [ "$option" -eq 1 ]; then
downloadTrack downloadTrack
elif [ "$option" -eq 2 ]; then elif [ "$option" -eq 2 ]; then

View file

@ -12,4 +12,4 @@ QUALITY="LOSSLESS"
COVER_RESOLUTION="1280" COVER_RESOLUTION="1280"
# If there is any problem with the API, Tidler will attempt to download the track again -> possible values are "1" to "100" # If there is any problem with the API, Tidler will attempt to download the track again -> possible values are "1" to "100"
MAX_ATTEMPTS="10" MAX_ATTEMPTS="15"