feat: download implementation

This commit is contained in:
2026-02-19 13:18:47 +01:00
parent f79836b11e
commit 1026868e01
4 changed files with 112 additions and 38 deletions

View File

@@ -1,5 +1,11 @@
package lib package lib
import (
"io"
"net/http"
"os"
)
const ( const (
DEFAULT_DOWNLOAD_SERVICE = "tidal" DEFAULT_DOWNLOAD_SERVICE = "tidal"
DEFAULT_DOWNLOAD_OUTPUT_FOLDER = "." DEFAULT_DOWNLOAD_OUTPUT_FOLDER = "."
@@ -17,10 +23,9 @@ type DownloadRequest struct {
SpotifyID string SpotifyID string
} }
func (app *App) Download(url string, outputFolder string, serviceString string) error { func (app *App) Download(url string, outputFile string, serviceString string, quality string) error {
if outputFolder == "" { var downloadUrl string
outputFolder = DEFAULT_DOWNLOAD_OUTPUT_FOLDER var fileName string
}
if serviceString == "" { if serviceString == "" {
serviceString = DEFAULT_DOWNLOAD_SERVICE serviceString = DEFAULT_DOWNLOAD_SERVICE
@@ -33,12 +38,6 @@ func (app *App) Download(url string, outputFolder string, serviceString string)
switch urlType { switch urlType {
case UrlTypeTrack: case UrlTypeTrack:
// metadata, err := app.GetTrackMetadata(url)
// if err != nil {
// return err
// }
// println(metadata.Data.TrackUnion.Id)
songlink, err := app.ConvertSongUrl(url) songlink, err := app.ConvertSongUrl(url)
if err != nil { if err != nil {
return err return err
@@ -49,17 +48,47 @@ func (app *App) Download(url string, outputFolder string, serviceString string)
return err return err
} }
// err = app.DownloadFromTidal(tidalId) downloadUrl, err = app.GetTidalDownloadUrl(tidalId, quality)
url, err = app.GetTidalDownloadUrl(tidalId, "LOSSLESS")
if err != nil { if err != nil {
return err return err
} }
println(url) }
metadata, err := app.GetTrackMetadata(url)
if err != nil {
return err
}
outputFile, err = BuildFileOutput(outputFile, fileName, metadata)
if err != nil {
return err
}
err = app.DownloadFromUrl(downloadUrl, outputFile)
if err != nil {
return err
} }
return nil return nil
} }
func (app *App) DownloadTrack(dr DownloadRequest) (bool, error) { func (app *App) DownloadFromUrl(url string, outputFilePath string) error {
return false, nil outputFile, err := os.Create(outputFilePath)
if err != nil {
return err
}
defer outputFile.Close()
res, err := http.Get(url)
if err != nil {
return err
}
defer res.Body.Close()
_, err = io.Copy(outputFile, res.Body)
if err != nil {
return err
}
return nil
} }

View File

@@ -59,7 +59,7 @@ type VideoAssociations struct {
TotalCount int64 `json:"totalCount"` TotalCount int64 `json:"totalCount"`
} }
type AssociationsV3 struct { type Associations struct {
AudioAssociations AudioAssociations `json:"audioAssociations"` AudioAssociations AudioAssociations `json:"audioAssociations"`
VideoAssociations VideoAssociations `json:"videoAssociations"` VideoAssociations VideoAssociations `json:"videoAssociations"`
} }
@@ -73,12 +73,18 @@ type Duration struct {
} }
type FirstArtist struct { type FirstArtist struct {
Items []map[string]interface{} `json:"items"` Items []ArtistItems `json:"items"`
TotalCount int64 `json:"totalCount"` TotalCount int64 `json:"totalCount"`
}
type ArtistItems struct {
Profile struct {
Name string `json:"name"`
} `json:"profile"`
} }
type OtherArtists struct { type OtherArtists struct {
Items []interface{} `json:"items"` Items []ArtistItems `json:"items"`
} }
type Playability struct { type Playability struct {
@@ -87,23 +93,23 @@ type Playability struct {
} }
type TrackUnion struct { type TrackUnion struct {
TypeName string `json:"__typename"` TypeName string `json:"__typename"`
AlbumOfTrack AlbumOfTrack `json:"albumOfTrack"` AlbumOfTrack AlbumOfTrack `json:"albumOfTrack"`
AssociationsV3 AssociationsV3 `json:"associationsV3"` Associations Associations `json:"associationsV3"`
ContentRating ContentRating `json:"contentRating"` ContentRating ContentRating `json:"contentRating"`
Duration Duration `json:"duration"` Duration Duration `json:"duration"`
FirstArtist FirstArtist `json:"firstArtist"` FirstArtist FirstArtist `json:"firstArtist"`
Id string `json:"id"` Id string `json:"id"`
MediaType string `json:"mediaType"` MediaType string `json:"mediaType"`
Name string `json:"name"` Name string `json:"name"`
OtherArtists OtherArtists `json:"otherArtists"` OtherArtists OtherArtists `json:"otherArtists"`
Playability Playability `json:"playability"` Playability Playability `json:"playability"`
Playcount string `json:"playcount"` Playcount string `json:"playcount"`
Saved bool `json:"saved"` Saved bool `json:"saved"`
SharingInfo interface{} `json:"sharingInfo"` SharingInfo interface{} `json:"sharingInfo"`
TrackNumber int64 `json:"trackNumber"` TrackNumber int64 `json:"trackNumber"`
Uri string `json:"uri"` Uri string `json:"uri"`
VisualIdentity interface{} `json:"visualIdentity"` VisualIdentity interface{} `json:"visualIdentity"`
} }
type Data struct { type Data struct {

View File

@@ -2,6 +2,8 @@ package lib
import ( import (
"errors" "errors"
"fmt"
"path"
"strings" "strings"
) )
@@ -38,3 +40,39 @@ func ParseTrackId(url string) (string, error) {
return tmp2[0], nil return tmp2[0], nil
} }
func BuildFileName(metadata TrackMetadata) (string, error) {
var result string
var artists string
firstArtistLen := len(metadata.Data.TrackUnion.FirstArtist.Items)
if firstArtistLen == 0 {
return result, errors.New("What? This should never happen.")
}
artists = metadata.Data.TrackUnion.FirstArtist.Items[firstArtistLen-1].Profile.Name
for _, artist := range(metadata.Data.TrackUnion.OtherArtists.Items) {
artists += ", " + artist.Profile.Name
}
result = fmt.Sprintf("%s - %s", metadata.Data.TrackUnion.Name, artists)
return result, nil
}
func BuildFileOutput(outputFile string, fileName string, metadata TrackMetadata) (string, error) {
var result string
fileName, err := BuildFileName(metadata)
if err != nil {
return result, err
}
if outputFile == "" {
result = path.Join(DEFAULT_DOWNLOAD_OUTPUT_FOLDER, fileName)
} else {
result = outputFile
}
return result, nil
}

View File

@@ -41,7 +41,8 @@ func main() {
}, },
Action: func(ctx context.Context, cmd *cli.Command) error { Action: func(ctx context.Context, cmd *cli.Command) error {
song_url := cmd.Args().First() song_url := cmd.Args().First()
err := app.Download(song_url, outputFolder, service) quality := "LOSSLESS"
err := app.Download(song_url, outputFolder, service, quality)
return err return err
}, },
}, },