-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Matt Gleich <[email protected]>
- Loading branch information
Showing
6 changed files
with
173 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,52 @@ | ||
package applemusic | ||
|
||
import "github.com/go-chi/chi/v5" | ||
import ( | ||
"time" | ||
|
||
"github.com/gleich/lcp-v2/internal/cache" | ||
"github.com/gleich/lumber/v3" | ||
"github.com/go-chi/chi/v5" | ||
) | ||
|
||
type cacheData struct { | ||
RecentlyPlayed []song `json:"recently_played"` | ||
Playlists map[string]playlist `json:"playlists"` | ||
} | ||
|
||
func cacheUpdate() (cacheData, error) { | ||
recentlyPlayed, err := fetchRecentlyPlayed() | ||
if err != nil { | ||
return cacheData{}, err | ||
} | ||
|
||
playlistsIDs := []string{ | ||
"p.LV0PXNoCl0EpDLW", // DIVORCED DAD | ||
"p.qQXLxPLtA75zg8e", // HIGHSCHOOL 1989 | ||
"p.LV0PX3EIl0EpDLW", // jazz | ||
} | ||
playlists := map[string]playlist{} | ||
for _, id := range playlistsIDs { | ||
playlistData, err := fetchPlaylist(id) | ||
if err != nil { | ||
return cacheData{}, err | ||
} | ||
playlists[id] = playlistData | ||
} | ||
|
||
return cacheData{ | ||
RecentlyPlayed: recentlyPlayed, | ||
Playlists: playlists, | ||
}, nil | ||
} | ||
|
||
func Setup(router *chi.Mux) { | ||
data, err := cacheUpdate() | ||
if err != nil { | ||
lumber.Fatal(err, "initial fetch of cache data failed") | ||
} | ||
|
||
applemusicCache := cache.NewCache("applemusic", data) | ||
router.Get("/applemusic/cache", applemusicCache.ServeHTTP()) | ||
go applemusicCache.StartPeriodicUpdate(cacheUpdate, 1*time.Minute) | ||
lumber.Done("setup apple music cache") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package applemusic | ||
|
||
import ( | ||
"path" | ||
"time" | ||
|
||
"github.com/gleich/lumber/v3" | ||
) | ||
|
||
type playlist struct { | ||
Name string `json:"name"` | ||
Tracks []song `json:"tracks"` | ||
LastModified time.Time `json:"last_modified"` | ||
} | ||
|
||
type playlistTracksResponse struct { | ||
Next string `json:"next"` | ||
Data []songResponse `json:"data"` | ||
} | ||
|
||
type playlistResponse struct { | ||
Data []struct { | ||
Attributes struct { | ||
LastModifiedDate time.Time `json:"lastModifiedDate"` | ||
Name string `json:"name"` | ||
} `json:"attributes"` | ||
} `json:"data"` | ||
} | ||
|
||
func fetchPlaylist(id string) (playlist, error) { | ||
playlistData, err := sendAPIRequest[playlistResponse](path.Join("v1/me/library/playlists/", id)) | ||
if err != nil { | ||
lumber.Error(err, "failed to fetch playlist for", id) | ||
return playlist{}, err | ||
} | ||
|
||
var totalResponseData []songResponse | ||
trackData, err := sendAPIRequest[playlistTracksResponse]( | ||
path.Join("v1/me/library/playlists/", id, "tracks"), | ||
) | ||
if err != nil { | ||
lumber.Error(err, "failed to get tracks for playlist with id of", id) | ||
} | ||
totalResponseData = append(totalResponseData, trackData.Data...) | ||
for trackData.Next != "" { | ||
trackData, err = sendAPIRequest[playlistTracksResponse](trackData.Next) | ||
if err != nil { | ||
lumber.Error(err, "failed to paginate through tracks for playlist with id of", id) | ||
} | ||
} | ||
|
||
var tracks []song | ||
for _, t := range totalResponseData { | ||
tracks = append(tracks, songFromSongResponse(t)) | ||
} | ||
|
||
return playlist{ | ||
Name: playlistData.Data[0].Attributes.Name, | ||
LastModified: playlistData.Data[0].Attributes.LastModifiedDate, | ||
Tracks: tracks, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,20 @@ | ||
package applemusic | ||
|
||
import ( | ||
"encoding/json" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/gleich/lumber/v3" | ||
) | ||
|
||
type recentlyPlayedResponse struct { | ||
Next string `json:"next"` | ||
Data songListData `json:"data"` | ||
Data []songResponse `json:"data"` | ||
} | ||
|
||
func FetchRecentlyPlayed() { | ||
func fetchRecentlyPlayed() ([]song, error) { | ||
response, err := sendAPIRequest[recentlyPlayedResponse]( | ||
"https://api.music.apple.com/v1/me/recent/played/tracks", | ||
"v1/me/recent/played/tracks", | ||
) | ||
if err != nil { | ||
lumber.Fatal(err, "failed to send request for recently played songs") | ||
return []song{}, err | ||
} | ||
|
||
var songs []song | ||
for _, s := range response.Data { | ||
songs = append(songs, song{ | ||
Track: s.Attributes.Name, | ||
Artist: s.Attributes.ArtistName, | ||
Album: s.Attributes.AlbumName, | ||
Genres: s.Attributes.GenreNames, | ||
ReleaseDate: s.Attributes.ReleaseDate, | ||
DurationInMillis: s.Attributes.DurationInMillis, | ||
AlbumArtURL: strings.ReplaceAll(strings.ReplaceAll( | ||
s.Attributes.Artwork.URL, | ||
"{w}", | ||
strconv.Itoa(s.Attributes.Artwork.Width), | ||
), "{h}", strconv.Itoa(s.Attributes.Artwork.Height)), | ||
URL: s.Attributes.URL, | ||
}) | ||
songs = append(songs, songFromSongResponse(s)) | ||
} | ||
|
||
encodedData, _ := json.Marshal(songs) | ||
lumber.Debug(string(encodedData)) | ||
return songs, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters