diff --git a/lib/download.go b/lib/download.go index e8693ab..83023fb 100644 --- a/lib/download.go +++ b/lib/download.go @@ -101,18 +101,61 @@ func (app *App) DownloadPlaylist(url string, outputFile string, service string, return nil } +func (app *App) GetDownloadUrlOrFallback(askedService string, quality string, songlink SongLinkResponse) (string, error) { + servicesToTry := []string{} + + switch askedService { + default: + case "tidal": + servicesToTry = []string{"tidal", "amazon", "qoboz"} + break + case "amazon": + servicesToTry = []string{"amazon", "tidal", "qoboz"} + break + case "quoboz": + servicesToTry = []string{"quoboz", "tidal", "amazon"} + break + } + + var downloadUrl string + var lastError error + for _, service := range servicesToTry { + switch service { + case "tidal": + if songlink.LinksByPlatform.Tidal == nil { + continue + } + + tidalId, err := app.GetTidalIdFromSonglink(songlink) + if err != nil { + lastError = err + continue + } + + downloadUrl, err = app.GetTidalDownloadUrl(tidalId, quality) + if err != nil { + lastError = err + continue + } + + break + } + } + + if lastError != nil || downloadUrl == "" { + return "", errors.New("Unable to download from any source.") + } + + return downloadUrl, nil +} + func (app *App) DownloadTrack(url string, outputFile string, service string, quality string, downloadInFolder bool) error { songlink, err := app.ConvertSongUrl(url) if err != nil { return err } - tidalId, err := app.GetTidalIdFromSonglink(songlink) - if err != nil { - return err - } - - downloadUrl, err := app.GetTidalDownloadUrl(tidalId, quality) + downloadUrl, err := app.GetDownloadUrlOrFallback(service, quality, songlink) if err != nil { return err } diff --git a/lib/songlink.go b/lib/songlink.go index 565da10..ea34c70 100644 --- a/lib/songlink.go +++ b/lib/songlink.go @@ -20,8 +20,8 @@ type SongLinkResponse struct { } type LinksByPlatform struct { - Deezer LinkByPlatform `json:"deezer"` - Tidal LinkByPlatform `json:"tidal"` + Deezer *LinkByPlatform `json:"deezer,omitempty"` + Tidal *LinkByPlatform `json:"tidal,omitempty"` } type LinkByPlatform struct { diff --git a/lib/tidal.go b/lib/tidal.go index 0534e25..994d02e 100644 --- a/lib/tidal.go +++ b/lib/tidal.go @@ -10,6 +10,8 @@ import ( "strings" ) +var ErrTidalUrlNotFound = errors.New("Tidal URL not found.") + func (app *App) LoadTidalApis() error { var found bool @@ -119,11 +121,15 @@ func (app *App) ParseTidalManifestFromBase64(manifestBase64 string) (TidalManife err = json.Unmarshal(manifestDecoded, &result) if err != nil { return result, err - } + } return result, nil } func (app *App) GetTidalIdFromSonglink(songlink SongLinkResponse) (string, error) { + if songlink.LinksByPlatform.Tidal == nil { + return "", ErrTidalUrlNotFound + } + return ParseTrackId(songlink.LinksByPlatform.Tidal.Url) }