fix
This commit is contained in:
parent
d9119832fe
commit
3e308ab9e7
100
main.go
100
main.go
@ -18,6 +18,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/abema/go-mp4"
|
"github.com/abema/go-mp4"
|
||||||
"github.com/grafov/m3u8"
|
"github.com/grafov/m3u8"
|
||||||
@ -919,6 +920,7 @@ func checkUrlPlaylist(url string) (string, string) {
|
|||||||
|
|
||||||
func getMeta(albumId string, token string, storefront string) (*AutoGenerated, error) {
|
func getMeta(albumId string, token string, storefront string) (*AutoGenerated, error) {
|
||||||
var mtype string
|
var mtype string
|
||||||
|
var page int
|
||||||
if strings.Contains(albumId, "pl.") {
|
if strings.Contains(albumId, "pl.") {
|
||||||
mtype = "playlists"
|
mtype = "playlists"
|
||||||
} else {
|
} else {
|
||||||
@ -953,6 +955,42 @@ func getMeta(albumId string, token string, storefront string) (*AutoGenerated, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if strings.Contains(albumId, "pl.") {
|
||||||
|
obj.Data[0].Attributes.ArtistName="Apple Music"
|
||||||
|
if len(obj.Data[0].Relationships.Tracks.Next) > 0 {
|
||||||
|
page=0
|
||||||
|
for{
|
||||||
|
page=page+100
|
||||||
|
pageStr := strconv.Itoa(page)
|
||||||
|
req, err := http.NewRequest("GET", fmt.Sprintf("https://amp-api.music.apple.com/v1/catalog/%s/%s/%s/tracks?offset=%s", storefront, mtype, albumId, pageStr), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||||
|
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
|
||||||
|
req.Header.Set("Origin", "https://music.apple.com")
|
||||||
|
do, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer do.Body.Close()
|
||||||
|
if do.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(do.Status)
|
||||||
|
}
|
||||||
|
obj2 := new(AutoGeneratedTrack)
|
||||||
|
err = json.NewDecoder(do.Body).Decode(&obj2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, value := range obj2.Data {
|
||||||
|
obj.Data[0].Relationships.Tracks.Data = append(obj.Data[0].Relationships.Tracks.Data, value)
|
||||||
|
}
|
||||||
|
if len(obj2.Next)==0{
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,6 +1039,9 @@ func rip(albumId string, token string, storefront string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
albumFolder := fmt.Sprintf("%s - %s", meta.Data[0].Attributes.ArtistName, meta.Data[0].Attributes.Name)
|
albumFolder := fmt.Sprintf("%s - %s", meta.Data[0].Attributes.ArtistName, meta.Data[0].Attributes.Name)
|
||||||
|
if strings.HasSuffix(albumFolder, ".") {
|
||||||
|
albumFolder = strings.ReplaceAll(albumFolder, ".", "")
|
||||||
|
}
|
||||||
sanAlbumFolder := filepath.Join("AM-DL downloads", forbiddenNames.ReplaceAllString(albumFolder, "_"))
|
sanAlbumFolder := filepath.Join("AM-DL downloads", forbiddenNames.ReplaceAllString(albumFolder, "_"))
|
||||||
os.MkdirAll(sanAlbumFolder, os.ModePerm)
|
os.MkdirAll(sanAlbumFolder, os.ModePerm)
|
||||||
fmt.Println(albumFolder)
|
fmt.Println(albumFolder)
|
||||||
@ -1609,6 +1650,7 @@ type AutoGenerated struct {
|
|||||||
} `json:"artists"`
|
} `json:"artists"`
|
||||||
Tracks struct {
|
Tracks struct {
|
||||||
Href string `json:"href"`
|
Href string `json:"href"`
|
||||||
|
Next string `json:"next"`
|
||||||
Data []struct {
|
Data []struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
@ -1666,3 +1708,61 @@ type AutoGenerated struct {
|
|||||||
} `json:"relationships"`
|
} `json:"relationships"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AutoGeneratedTrack struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
Next string `json:"next"`
|
||||||
|
Data []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
Attributes struct {
|
||||||
|
Previews []struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"previews"`
|
||||||
|
Artwork struct {
|
||||||
|
Width int `json:"width"`
|
||||||
|
Height int `json:"height"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
BgColor string `json:"bgColor"`
|
||||||
|
TextColor1 string `json:"textColor1"`
|
||||||
|
TextColor2 string `json:"textColor2"`
|
||||||
|
TextColor3 string `json:"textColor3"`
|
||||||
|
TextColor4 string `json:"textColor4"`
|
||||||
|
} `json:"artwork"`
|
||||||
|
ArtistName string `json:"artistName"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
DiscNumber int `json:"discNumber"`
|
||||||
|
GenreNames []string `json:"genreNames"`
|
||||||
|
HasTimeSyncedLyrics bool `json:"hasTimeSyncedLyrics"`
|
||||||
|
IsMasteredForItunes bool `json:"isMasteredForItunes"`
|
||||||
|
DurationInMillis int `json:"durationInMillis"`
|
||||||
|
ReleaseDate string `json:"releaseDate"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Isrc string `json:"isrc"`
|
||||||
|
AudioTraits []string `json:"audioTraits"`
|
||||||
|
HasLyrics bool `json:"hasLyrics"`
|
||||||
|
AlbumName string `json:"albumName"`
|
||||||
|
PlayParams struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
} `json:"playParams"`
|
||||||
|
TrackNumber int `json:"trackNumber"`
|
||||||
|
AudioLocale string `json:"audioLocale"`
|
||||||
|
ComposerName string `json:"composerName"`
|
||||||
|
} `json:"attributes"`
|
||||||
|
Relationships struct {
|
||||||
|
Artists struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
Data []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
Attributes struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"attributes"`
|
||||||
|
} `json:"data"`
|
||||||
|
} `json:"artists"`
|
||||||
|
} `json:"relationships"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
126
main_atmos.go
126
main_atmos.go
@ -18,6 +18,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/abema/go-mp4"
|
"github.com/abema/go-mp4"
|
||||||
"github.com/grafov/m3u8"
|
"github.com/grafov/m3u8"
|
||||||
@ -909,8 +910,26 @@ func checkUrl(url string) (string, string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkUrlPlaylist(url string) (string, string) {
|
||||||
|
pat := regexp.MustCompile(`^(?:https:\/\/(?:beta\.music|music)\.apple\.com\/(\w{2})(?:\/playlist|\/playlist\/.+))\/(?:id)?(pl\.[\w-]+)(?:$|\?)`)
|
||||||
|
matches := pat.FindAllStringSubmatch(url, -1)
|
||||||
|
|
||||||
|
if matches == nil {
|
||||||
|
return "", ""
|
||||||
|
} else {
|
||||||
|
return matches[0][1], matches[0][2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getMeta(albumId string, token string, storefront string) (*AutoGenerated, error) {
|
func getMeta(albumId string, token string, storefront string) (*AutoGenerated, error) {
|
||||||
req, err := http.NewRequest("GET", fmt.Sprintf("https://amp-api.music.apple.com/v1/catalog/%s/albums/%s", storefront, albumId), nil)
|
var mtype string
|
||||||
|
var page int
|
||||||
|
if strings.Contains(albumId, "pl.") {
|
||||||
|
mtype = "playlists"
|
||||||
|
} else {
|
||||||
|
mtype = "albums"
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest("GET", fmt.Sprintf("https://amp-api.music.apple.com/v1/catalog/%s/%s/%s", storefront,mtype, albumId), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -939,6 +958,42 @@ func getMeta(albumId string, token string, storefront string) (*AutoGenerated, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if strings.Contains(albumId, "pl.") {
|
||||||
|
obj.Data[0].Attributes.ArtistName="Apple Music"
|
||||||
|
if len(obj.Data[0].Relationships.Tracks.Next) > 0 {
|
||||||
|
page=0
|
||||||
|
for{
|
||||||
|
page=page+100
|
||||||
|
pageStr := strconv.Itoa(page)
|
||||||
|
req, err := http.NewRequest("GET", fmt.Sprintf("https://amp-api.music.apple.com/v1/catalog/%s/%s/%s/tracks?offset=%s", storefront, mtype, albumId, pageStr), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||||
|
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
|
||||||
|
req.Header.Set("Origin", "https://music.apple.com")
|
||||||
|
do, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer do.Body.Close()
|
||||||
|
if do.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(do.Status)
|
||||||
|
}
|
||||||
|
obj2 := new(AutoGeneratedTrack)
|
||||||
|
err = json.NewDecoder(do.Body).Decode(&obj2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, value := range obj2.Data {
|
||||||
|
obj.Data[0].Relationships.Tracks.Data = append(obj.Data[0].Relationships.Tracks.Data, value)
|
||||||
|
}
|
||||||
|
if len(obj2.Next)==0{
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -985,6 +1040,9 @@ func rip(albumId string, token string, storefront string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
albumFolder := fmt.Sprintf("%s - %s", meta.Data[0].Attributes.ArtistName, meta.Data[0].Attributes.Name)
|
albumFolder := fmt.Sprintf("%s - %s", meta.Data[0].Attributes.ArtistName, meta.Data[0].Attributes.Name)
|
||||||
|
if strings.HasSuffix(albumFolder, ".") {
|
||||||
|
albumFolder = strings.ReplaceAll(albumFolder, ".", "")
|
||||||
|
}
|
||||||
sanAlbumFolder := filepath.Join("AM-DL downloads", forbiddenNames.ReplaceAllString(albumFolder, "_"))
|
sanAlbumFolder := filepath.Join("AM-DL downloads", forbiddenNames.ReplaceAllString(albumFolder, "_"))
|
||||||
os.MkdirAll(sanAlbumFolder, os.ModePerm)
|
os.MkdirAll(sanAlbumFolder, os.ModePerm)
|
||||||
fmt.Println(albumFolder)
|
fmt.Println(albumFolder)
|
||||||
@ -1056,7 +1114,12 @@ func main() {
|
|||||||
albumTotal := len(os.Args[1:])
|
albumTotal := len(os.Args[1:])
|
||||||
for albumNum, url := range os.Args[1:] {
|
for albumNum, url := range os.Args[1:] {
|
||||||
fmt.Printf("Album %d of %d:\n", albumNum+1, albumTotal)
|
fmt.Printf("Album %d of %d:\n", albumNum+1, albumTotal)
|
||||||
storefront, albumId := checkUrl(url)
|
var storefront, albumId string
|
||||||
|
if strings.Contains(url, "playlist") {
|
||||||
|
storefront, albumId = checkUrlPlaylist(url)
|
||||||
|
} else {
|
||||||
|
storefront, albumId = checkUrl(url)
|
||||||
|
}
|
||||||
if albumId == "" {
|
if albumId == "" {
|
||||||
fmt.Printf("Invalid URL: %s\n", url)
|
fmt.Printf("Invalid URL: %s\n", url)
|
||||||
continue
|
continue
|
||||||
@ -1586,6 +1649,7 @@ type AutoGenerated struct {
|
|||||||
} `json:"artists"`
|
} `json:"artists"`
|
||||||
Tracks struct {
|
Tracks struct {
|
||||||
Href string `json:"href"`
|
Href string `json:"href"`
|
||||||
|
Next string `json:"next"`
|
||||||
Data []struct {
|
Data []struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
@ -1643,3 +1707,61 @@ type AutoGenerated struct {
|
|||||||
} `json:"relationships"`
|
} `json:"relationships"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AutoGeneratedTrack struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
Next string `json:"next"`
|
||||||
|
Data []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
Attributes struct {
|
||||||
|
Previews []struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"previews"`
|
||||||
|
Artwork struct {
|
||||||
|
Width int `json:"width"`
|
||||||
|
Height int `json:"height"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
BgColor string `json:"bgColor"`
|
||||||
|
TextColor1 string `json:"textColor1"`
|
||||||
|
TextColor2 string `json:"textColor2"`
|
||||||
|
TextColor3 string `json:"textColor3"`
|
||||||
|
TextColor4 string `json:"textColor4"`
|
||||||
|
} `json:"artwork"`
|
||||||
|
ArtistName string `json:"artistName"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
DiscNumber int `json:"discNumber"`
|
||||||
|
GenreNames []string `json:"genreNames"`
|
||||||
|
HasTimeSyncedLyrics bool `json:"hasTimeSyncedLyrics"`
|
||||||
|
IsMasteredForItunes bool `json:"isMasteredForItunes"`
|
||||||
|
DurationInMillis int `json:"durationInMillis"`
|
||||||
|
ReleaseDate string `json:"releaseDate"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Isrc string `json:"isrc"`
|
||||||
|
AudioTraits []string `json:"audioTraits"`
|
||||||
|
HasLyrics bool `json:"hasLyrics"`
|
||||||
|
AlbumName string `json:"albumName"`
|
||||||
|
PlayParams struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
} `json:"playParams"`
|
||||||
|
TrackNumber int `json:"trackNumber"`
|
||||||
|
AudioLocale string `json:"audioLocale"`
|
||||||
|
ComposerName string `json:"composerName"`
|
||||||
|
} `json:"attributes"`
|
||||||
|
Relationships struct {
|
||||||
|
Artists struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
Data []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
Attributes struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"attributes"`
|
||||||
|
} `json:"data"`
|
||||||
|
} `json:"artists"`
|
||||||
|
} `json:"relationships"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
@ -921,6 +921,7 @@ func checkUrlPlaylist(url string) (string, string) {
|
|||||||
|
|
||||||
func getMeta(albumId string, token string, storefront string) (*AutoGenerated, error) {
|
func getMeta(albumId string, token string, storefront string) (*AutoGenerated, error) {
|
||||||
var mtype string
|
var mtype string
|
||||||
|
var page int
|
||||||
if strings.Contains(albumId, "pl.") {
|
if strings.Contains(albumId, "pl.") {
|
||||||
mtype = "playlists"
|
mtype = "playlists"
|
||||||
} else {
|
} else {
|
||||||
@ -955,6 +956,42 @@ func getMeta(albumId string, token string, storefront string) (*AutoGenerated, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if strings.Contains(albumId, "pl.") {
|
||||||
|
obj.Data[0].Attributes.ArtistName="Apple Music"
|
||||||
|
if len(obj.Data[0].Relationships.Tracks.Next) > 0 {
|
||||||
|
page=0
|
||||||
|
for{
|
||||||
|
page=page+100
|
||||||
|
pageStr := strconv.Itoa(page)
|
||||||
|
req, err := http.NewRequest("GET", fmt.Sprintf("https://amp-api.music.apple.com/v1/catalog/%s/%s/%s/tracks?offset=%s", storefront, mtype, albumId, pageStr), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||||
|
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
|
||||||
|
req.Header.Set("Origin", "https://music.apple.com")
|
||||||
|
do, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer do.Body.Close()
|
||||||
|
if do.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(do.Status)
|
||||||
|
}
|
||||||
|
obj2 := new(AutoGeneratedTrack)
|
||||||
|
err = json.NewDecoder(do.Body).Decode(&obj2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, value := range obj2.Data {
|
||||||
|
obj.Data[0].Relationships.Tracks.Data = append(obj.Data[0].Relationships.Tracks.Data, value)
|
||||||
|
}
|
||||||
|
if len(obj2.Next)==0{
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1011,6 +1048,9 @@ func rip(albumId string, token string, storefront string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
albumFolder := fmt.Sprintf("%s - %s", meta.Data[0].Attributes.ArtistName, meta.Data[0].Attributes.Name)
|
albumFolder := fmt.Sprintf("%s - %s", meta.Data[0].Attributes.ArtistName, meta.Data[0].Attributes.Name)
|
||||||
|
if strings.HasSuffix(albumFolder, ".") {
|
||||||
|
albumFolder = strings.ReplaceAll(albumFolder, ".", "")
|
||||||
|
}
|
||||||
sanAlbumFolder := filepath.Join("AM-DL downloads", forbiddenNames.ReplaceAllString(albumFolder, "_"))
|
sanAlbumFolder := filepath.Join("AM-DL downloads", forbiddenNames.ReplaceAllString(albumFolder, "_"))
|
||||||
os.MkdirAll(sanAlbumFolder, os.ModePerm)
|
os.MkdirAll(sanAlbumFolder, os.ModePerm)
|
||||||
fmt.Println(albumFolder)
|
fmt.Println(albumFolder)
|
||||||
@ -1648,6 +1688,7 @@ type AutoGenerated struct {
|
|||||||
} `json:"artists"`
|
} `json:"artists"`
|
||||||
Tracks struct {
|
Tracks struct {
|
||||||
Href string `json:"href"`
|
Href string `json:"href"`
|
||||||
|
Next string `json:"next"`
|
||||||
Data []struct {
|
Data []struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
@ -1705,3 +1746,61 @@ type AutoGenerated struct {
|
|||||||
} `json:"relationships"`
|
} `json:"relationships"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AutoGeneratedTrack struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
Next string `json:"next"`
|
||||||
|
Data []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
Attributes struct {
|
||||||
|
Previews []struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"previews"`
|
||||||
|
Artwork struct {
|
||||||
|
Width int `json:"width"`
|
||||||
|
Height int `json:"height"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
BgColor string `json:"bgColor"`
|
||||||
|
TextColor1 string `json:"textColor1"`
|
||||||
|
TextColor2 string `json:"textColor2"`
|
||||||
|
TextColor3 string `json:"textColor3"`
|
||||||
|
TextColor4 string `json:"textColor4"`
|
||||||
|
} `json:"artwork"`
|
||||||
|
ArtistName string `json:"artistName"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
DiscNumber int `json:"discNumber"`
|
||||||
|
GenreNames []string `json:"genreNames"`
|
||||||
|
HasTimeSyncedLyrics bool `json:"hasTimeSyncedLyrics"`
|
||||||
|
IsMasteredForItunes bool `json:"isMasteredForItunes"`
|
||||||
|
DurationInMillis int `json:"durationInMillis"`
|
||||||
|
ReleaseDate string `json:"releaseDate"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Isrc string `json:"isrc"`
|
||||||
|
AudioTraits []string `json:"audioTraits"`
|
||||||
|
HasLyrics bool `json:"hasLyrics"`
|
||||||
|
AlbumName string `json:"albumName"`
|
||||||
|
PlayParams struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
} `json:"playParams"`
|
||||||
|
TrackNumber int `json:"trackNumber"`
|
||||||
|
AudioLocale string `json:"audioLocale"`
|
||||||
|
ComposerName string `json:"composerName"`
|
||||||
|
} `json:"attributes"`
|
||||||
|
Relationships struct {
|
||||||
|
Artists struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
Data []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
Attributes struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"attributes"`
|
||||||
|
} `json:"data"`
|
||||||
|
} `json:"artists"`
|
||||||
|
} `json:"relationships"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user