Merge version 0.3.0 from dev

This commit is contained in:
Medvidek77 2025-03-22 00:38:22 +01:00
commit af36446526
6 changed files with 357 additions and 21 deletions

View file

@ -2,23 +2,60 @@
*Tidal music downloader based on the hifi-tui API* *Tidal music downloader based on the hifi-tui API*
### https://github.com/sachinsenal0x64/Hifi-Tui
## Requirements ## Requirements
<<<<<<< HEAD
- `bash`, `curl`, `jq`, `awk` - `bash`, `curl`, `jq`, `awk`
=======
- `bash`, `curl`, `jq`, `awk`, `flac`
>>>>>>> dev
## TODO ## TODO
- Create install scripts/guides - Create install scripts/guides (WIP)
- Migrate from Bash to a POSIX-compliant shell - Migrate from Bash to a POSIX-compliant shell
<<<<<<< HEAD
- Add vorbis tags - Add vorbis tags
- Lyrics download - Lyrics download
- Implement search & download for playlists, albums, and artists - Implement search & download for playlists, albums, and artists
=======
- Add Cover, and other metadata to vorbis tag (Almost done)
- Lyrics download (WIP)
- Implement search & download for playlists, albums, and artists (WIP)
>>>>>>> dev
- 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)
- Add a configuration file - Add a configuration file (Done)
- Add default save directory - Add default save directory (Done)
- Error handling (WIP)
## Using ## Using
<<<<<<< HEAD
- Download repository: `git clone https://git.medvidek77.tech/Medvidek77/tidler.git && cd tidler` - Download repository: `git clone https://git.medvidek77.tech/Medvidek77/tidler.git && cd tidler`
- (Optional) use unstable version: `git checkout dev` - (Optional) use unstable version: `git checkout dev`
- Add permissions as root: `chmod +x src/tidler` - Add permissions as root: `chmod +x src/tidler`
- Run: `src/tidler` - Run: `src/tidler`
- Enjoy! :) - Enjoy! :)
=======
- Download repository:
```
git clone https://git.medvidek77.tech/Medvidek77/tidler.git && cd tidler
```
- (Optional) use unstable version:
```
git checkout dev
```
- Add permissions as root:
```
chmod +x src/tidler
```
- Run:
```
src/tidler
```
- Enjoy! :)
>>>>>>> dev

View file

@ -1,6 +1,7 @@
# Maintainer: Medvidek77 <medvidek77@tuta.io> # Maintainer: Medvidek77 <medvidek77@tuta.io>
pkgname=tidler pkgname=tidler
<<<<<<< HEAD
pkgver=0.2 pkgver=0.2
pkgrel=2 pkgrel=2
pkgdesc="Tidal music downloader based on the hifi-tui API" pkgdesc="Tidal music downloader based on the hifi-tui API"
@ -8,11 +9,23 @@ arch=('any')
url="https://git.medvidek77.tech/Medvidek77/tidler" url="https://git.medvidek77.tech/Medvidek77/tidler"
license=('BSD3-Clause') license=('BSD3-Clause')
depends=('bash' 'curl' 'jq' 'awk') depends=('bash' 'curl' 'jq' 'awk')
=======
pkgver=0.3.0
pkgrel=3
pkgdesc="Tidal music downloader based on the hifi-tui API"
arch=('any')
url="https://git.medvidek77.tech/Medvidek77/tidler"
license=('BSD-3-Clause')
depends=('bash' 'curl' 'jq' 'awk' 'flac')
>>>>>>> dev
source=("git+$url.git#branch=stable") source=("git+$url.git#branch=stable")
sha256sums=('SKIP') sha256sums=('SKIP')
package() { package() {
cd "$srcdir/$pkgname" cd "$srcdir/$pkgname"
install -Dm755 src/tidler "$pkgdir/usr/bin/tidler" install -Dm755 src/tidler "$pkgdir/usr/bin/tidler"
install -Dm644 src/tidler.conf "$pkgdir/usr/bin/tidler.conf"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
} }
backup=('usr/bin/tidler.conf')

View file

@ -0,0 +1,21 @@
# Maintainer: Medvidek77 <medvidek77@tuta.io>
pkgname=tidler
pkgver=0.3.0
pkgrel=3
pkgdesc="Tidal music downloader based on the hifi-tui API"
arch=('any')
url="https://git.medvidek77.tech/Medvidek77/tidler"
license=('BSD-3-Clause')
depends=('bash' 'curl' 'jq' 'awk' 'flac')
source=("git+$url.git#branch=dev")
sha256sums=('SKIP')
package() {
cd "$srcdir/$pkgname"
install -Dm755 src/tidler "$pkgdir/usr/bin/tidler"
install -Dm644 src/tidler.conf "$pkgdir/usr/bin/tidler.conf"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}
backup=('usr/bin/tidler.conf')

Binary file not shown.

View file

@ -1,21 +1,142 @@
#!/bin/bash #!/bin/bash
. tidler.conf # Load ENVs from config file
version="0.3.0"
if [ -n "$PROXY_URL" ]; then
proxy_url="$PROXY_URL"
else
proxy_url="https://hifi-04ed2aaea09a.herokuapp.com" # Default value
fi
if [ -n "$QUALITY" ]; then
if [ "$QUALITY" = "LOSSLESS" -o "$QUALITY" = "HI_RES" ]; then
quality="$QUALITY"
else
echo "Bad QUALITY option. Only allowed are \"LOSSLESS\", \"HI_RES\"."
echo "Using default value..."
quality="LOSSLESS" # Default value
fi
else
quality="LOSSLESS" # Default value
fi
if [ -n "$COVER_RESOLUTION" ]; then
if [ "$COVER_RESOLUTION" = "1280" -o "$COVER_RESOLUTION" = "640" -o "$COVER_RESOLUTION" = "80" ]; then
cover_resolution="$COVER_RESOLUTION"
else
echo "Bad COVER_RESOLUTION option. Only allowed are \"1280\", \"640\", \"80\"."
echo "Using default value..."
cover_resolution="1280" # Default value
fi
else
cover_resolution="1280" # Default value
fi
if [ -n "$MAX_ATTEMPTS" ]; then
if [ "$MAX_ATTEMPTS" -ge 1 -a "$MAX_ATTEMPTS" -le 100 ]; then
max_attempts="$MAX_ATTEMPTS"
else
echo "Bad MAX_ATTEMPTS option. Allowed are numbers from 1 to 100."
echo "Using default value..."
max_attempts="10" # Default value
fi
else
max_attempts="10" # Default value
fi
downloadTrack() { downloadTrack() {
if [ "$#" -ge 1 ]; then if [ "$#" -ge 1 ]; then
echo "Downloading track with ID: $1" echo "Downloading track with ID: $1"
id="$1" id="$1"
else else
echo "Enter track ID:" echo "Enter track ID:"
read -r id read -r id
fi fi
json_data=$(curl -s "https://tidal.401658.xyz/track/?id=$id&quality=LOSSLESS")
track_name=$(echo "$json_data" | jq -r '.[0].title')
artist_name=$(echo "$json_data" | jq -r '.[0].artist.name')
url=$(echo "$json_data" | jq -r '.[-1].OriginalTrackUrl')
filename="$artist_name - $track_name.flac" if [ "$#" -ge 2 ]; then
filename=$(echo "$filename" | tr '/' '-') album_dir="$2"
curl "$url" -o "$filename" else
album_dir=""
fi
attempt_num=1
success=false
while [ $attempt_num -le $max_attempts ]; do
json_data=$(curl -# "$proxy_url/track/?id=$id&quality=$quality")
if [ $? -eq 0 ]; then
track_name=$(echo "$json_data" | jq -r '.[0].title // empty')
if [ -n "$track_name" ]; then
artist_name=$(echo "$json_data" | jq -r '.[0].artist.name // empty')
if [ -n "$artist_name" ]; then
album_name=$(echo "$json_data" | jq -r '.[0].album.title // empty')
if [ -n "$album_name" ]; then
url=$(echo "$json_data" | jq -r '.[-1].OriginalTrackUrl // empty')
if [ -n "$url" ]; then
cover_data=$(curl -# "$proxy_url/cover/?id=$id")
cover_url=$(echo "$cover_data" | jq -r '.[]["1280"] // empty')
if [ -n "$cover_url" ]; then
track_number=$(echo "$json_data" | jq -r '.[0].trackNumber')
filename="$track_name.flac"
cover_name="cover.png"
success=true
break
fi
fi
fi
fi
fi
fi
if [ "$success" = false ]; then
echo "Attempt $attempt_num failed. Retrying..."
((attempt_num++))
sleep "1.$(tr -cd 0-9 </dev/urandom | head -c 5)"
fi
done
if [ "$success" = false ]; then
echo "Failed to download after $max_attempts attempts."
exit 1
fi
if [ -n "$DOWNLOADS_DIR" ]; then
download_dir="$DOWNLOADS_DIR"
else
download_dir="$(pwd)"
fi
if [ -z "$album_dir" ]; then
final_path="$download_dir"
else
final_path="$download_dir/$album_dir"
fi
mkdir -p "$final_path"
curl -# "$url" -o "$final_path/$filename"
curl -# "$cover_url" -o "$final_path/$cover_name"
# Metadata
metaflac \
--set-tag="NAME=$track_name" \
--set-tag="ARTIST=$artist_name" \
--set-tag="ALBUM=$album_name" \
--set-tag="TRACKNUMBER=$track_number" \
--import-picture-from="$final_path/$cover_name" \
"$final_path/$filename"
} }
searchTrack() { searchTrack() {
@ -26,8 +147,8 @@ searchTrack() {
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 -s "https://tidal.401658.xyz/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)"')
tracks_list=() tracks_list=()
while IFS= read -r list; do while IFS= read -r list; do
tracks_list+=("$list") tracks_list+=("$list")
@ -51,7 +172,102 @@ searchTrack() {
done done
} }
echo "Welcome to TiDLer -> Tidal music downloader" && echo ""
downloadAlbum() {
id="$1"
if [ -n "$DOWNLOADS_DIR" ]; then
base_dir="$DOWNLOADS_DIR"
else
base_dir="$(pwd)"
fi
attempt_num=1
success=false
while [ $attempt_num -le $max_attempts ]; do
json_data=$(curl -# "$proxy_url/album/?id=$id&quality=$quality")
if [ $? -eq 0 ]; then
album_name=$(echo "$json_data" | jq -r '.[0].title')
artist_name=$(echo "$json_data" | jq -r '.[0].artist.name')
album_title="$artist_name - $album_name"
album_dir="$album_title"
album_tracks_ids=$(echo "$json_data" | jq -r '.[1].items[] | .item.id')
tracks_ids_list=()
while IFS= read -r list; do
tracks_ids_list+=("$list")
done <<< "$album_tracks_ids"
for track_id in "${tracks_ids_list[@]}"; do
downloadTrack "$track_id" "$album_dir"
done
success=true
break
else
echo "Attempt $attempt_num failed. Retrying..."
((attempt_num++))
sleep "1.$(tr -cd 0-9 </dev/urandom | head -c 5)"
fi
done
if [ "$success" = false ]; then
echo "Failed to download album after $max_attempts attempts."
exit 1
fi
}
searchAlbum() {
if [ "$#" -ge 1 ]; then
album_name="$1"
else
echo "Enter album name:"
read -r album_name
fi
album_name=$(echo "$album_name" | sed 's/ /%20/g')
attempt_num=1
success=false
while [ $attempt_num -le $max_attempts ]; do
albums=$(curl -# "$proxy_url/search/?al=$album_name" | jq -r '.albums.items[] | "\(.id): \(.title)"')
albums_list=()
while IFS= read -r list; do
albums_list+=("$list")
done <<< "$albums"
if [ "${#albums_list[@]}" -eq 0 ]; then
echo "No albums found. Retrying... (Attempt $attempt_num/$max_attempts)"
((attempt_num++))
sleep "1.$(tr -cd 0-9 </dev/urandom | head -c 5)"
else
PS3="Please select an album: "
select t in "${albums_list[@]}"; do
if [ -n "$t" ]; then
album_id=$(echo "$t" | awk -F ': ' '{print $1}')
echo "You selected: $t"
downloadAlbum "$album_id"
success=true
break
else
echo "Invalid selection. Please try again."
fi
done
if [ "$success" = true ]; then
break
fi
fi
done
if [ "$success" = false ]; then
echo "Failed to find and download album after $max_attempts attempts."
exit 1
fi
}
if [ "$1" = "search" ]; then if [ "$1" = "search" ]; then
if [ "$#" -ge 2 ]; then if [ "$#" -ge 2 ]; then
@ -67,13 +283,47 @@ elif [ "$1" = "download" ]; then
else else
downloadTrack downloadTrack
fi fi
elif [ "$1" = "album" ]; then
if [ "$#" -ge 2 ]; then
shift
jsw="$*"
searchAlbum "$jsw"
else
searchAlbum
fi
elif [ "$1" == "version" ]; then
echo "TiDLer $version by Medvidek77"
elif [ "$1" = "help" ]; then
echo "<MODE>"
echo ""
echo "If a valid parameter is provided, the corresponding function executes. Otherwise, TiDLer enters INTERACTIVE mode!"
echo ""
echo "<COMMANDS>"
echo ""
echo "search {track_name}-optional -> search any song"
echo ""
echo "download {song_id}-optional -> download any song"
echo ""
echo "album {album_name}-optional -> search and download any album"
echo ""
echo "version -> print TiDLer version"
echo ""
echo "help -> print this message and exit"
else else
echo "Choose 1 for download track or 2 for search track and download" echo "### Choose function! (Enter number) ###"
echo ""
echo "1. Download single track with ID"
echo ""
echo "2. Search single track with text"
echo ""
echo "3. Search and download whole album with text"
read option read option
if [ "$option" -eq 1 ]; then if [ "$option" -eq 1 ]; then
downloadTrack downloadTrack
elif [ "$option" -eq 2 ]; then elif [ "$option" -eq 2 ]; then
searchTrack searchTrack
elif [ "$option" -eq 3 ]; then
searchAlbum
fi fi
fi fi

15
src/tidler.conf Normal file
View file

@ -0,0 +1,15 @@
# Default download directory
DOWNLOADS_DIR="/home/$USER/Music"
# hifi-tui API server URL -> https://github.com/sachinsenal0x64/Hifi-Tui
# You can use "https://tidal.401658.xyz" with cache enabled
PROXY_URL="https://hifi-04ed2aaea09a.herokuapp.com"
# Set audio quality -> possible values are "LOSSLESS" and "HI_RES"
QUALITY="LOSSLESS"
# Set cover art resolution -> "1280" = 1280x1280, "640" = 640x640, "80" = 80x80
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"
MAX_ATTEMPTS="10"