feat: add playlist download

This commit is contained in:
2026-02-20 08:05:05 +01:00
parent 777fab8c9a
commit e4083c65c0
3 changed files with 86 additions and 8 deletions

View File

@@ -2,9 +2,13 @@ package lib
import ( import (
"errors" "errors"
"fmt"
"io" "io"
"net/http" "net/http"
"os" "os"
"path"
"strconv"
"time"
) )
const ( const (
@@ -36,14 +40,13 @@ func (app *App) Download(url string, outputFile string, service string, quality
switch urlType { switch urlType {
case UrlTypeTrack: case UrlTypeTrack:
if err := app.DownloadTrack(url, outputFile, service, quality); err != nil { if err := app.DownloadTrack(url, outputFile, service, quality, false); err != nil {
return err return err
} }
return nil return nil
case UrlTypePlaylist: case UrlTypePlaylist:
_, err := app.GetPlaylistMetadata(url) if err := app.DownloadPlaylist(url, outputFile, service, quality); err != nil {
if err != nil {
return err return err
} }
@@ -53,7 +56,48 @@ func (app *App) Download(url string, outputFile string, service string, quality
return errors.New("Invalid URL type.") return errors.New("Invalid URL type.")
} }
func (app *App) DownloadTrack(url string, outputFile, service string, quality string) error { func (app *App) DownloadPlaylist(url string, outputFile string, service string, quality string) error {
playlist, err := app.GetPlaylistMetadata(url)
if err != nil {
return err
}
var urls []string
for _, item := range playlist.Data.Playlist.Content.Items {
url, err := SpotifyUriToLink(item.Item.Data.Uri)
if err != nil {
return err
}
urls = append(urls, url)
}
trackListSize := len(urls)
for idx, url := range urls {
metadata, err := app.GetTrackMetadata(url)
if err != nil {
return err
}
artists, err := GetArtists(metadata)
if err != nil {
return err
}
fmt.Println("[" + strconv.Itoa(idx+1) + "/" + strconv.Itoa(trackListSize) + "] " + metadata.Data.TrackUnion.Name + " - " + artists)
if err := app.DownloadTrack(url, outputFile+"/", service, quality, true); err != nil {
return err
}
// Avoid getting rate limited
time.Sleep(800 * time.Millisecond)
}
return nil
}
func (app *App) DownloadTrack(url string, outputFile string, service string, quality string, downloadFromPlaylist bool) error {
songlink, err := app.ConvertSongUrl(url) songlink, err := app.ConvertSongUrl(url)
if err != nil { if err != nil {
return err return err
@@ -79,9 +123,17 @@ func (app *App) DownloadTrack(url string, outputFile, service string, quality st
return err return err
} }
outputFile, err = BuildFileOutput(outputFile, extension, metadata) if downloadFromPlaylist {
if err != nil { fileName, err := BuildFileName(metadata, extension)
return err if err != nil {
return err
}
outputFile = path.Join(outputFile, fileName)
} else {
outputFile, err = BuildFileOutput(outputFile, extension, metadata)
if err != nil {
return err
}
} }
fileExists, err := FileExists(outputFile) fileExists, err := FileExists(outputFile)

View File

@@ -127,7 +127,19 @@ type TrackMetadata struct {
type PlaylistMetadata struct { type PlaylistMetadata struct {
Data struct { Data struct {
Playlist struct { Playlist struct {
Name string `json:"name"` Name string `json:"name"`
Content struct {
Items []struct {
Item struct {
Data struct {
IdentityTrait struct {
Name string `json:"name"`
} `json:"identityTrait"`
Uri string `json:"uri"`
} `json:"data"`
} `json:"itemV3"`
} `json:"items"`
} `json:"content"`
} `json:"playlistV2"` } `json:"playlistV2"`
} `json:"data"` } `json:"data"`
} }

View File

@@ -15,6 +15,10 @@ const (
UrlTypePlaylist UrlTypePlaylist
) )
const (
BASE_SPOTIFY_TRACK_URL = "https://open.spotify.com/track/"
)
func ParseUrlType(url string) (UrlType, error) { func ParseUrlType(url string) (UrlType, error) {
if strings.Contains(url, "https://open.spotify.com/track") { if strings.Contains(url, "https://open.spotify.com/track") {
return UrlTypeTrack, nil return UrlTypeTrack, nil
@@ -131,3 +135,13 @@ func (app *App) InitSpotifyClient() error {
return nil return nil
} }
func SpotifyUriToLink(uri string) (string, error) {
spotifyId := strings.Split(uri, ":")
if len(spotifyId) != 3 {
return "", errors.New("Invalid URI parsed.")
}
return BASE_SPOTIFY_TRACK_URL + spotifyId[2], nil
}