Spotify: Loves export

This commit is contained in:
Philipp Wolfer 2023-11-22 11:52:28 +01:00
parent ed9debc127
commit 2e6319d296
No known key found for this signature in database
GPG key ID: 8FDF744D4919943B
3 changed files with 212 additions and 38 deletions

View file

@ -18,6 +18,7 @@ Scotty. If not, see <https://www.gnu.org/licenses/>.
package spotify
import (
"math"
"net/url"
"sort"
"strconv"
@ -128,51 +129,131 @@ func (b *SpotifyApiBackend) ExportListens(oldestTimestamp time.Time, results cha
progress <- p.Complete()
}
func (b *SpotifyApiBackend) ExportLoves(oldestTimestamp time.Time, results chan models.LovesResult, progress chan models.Progress) {
// Choose a high offset, we attempt to search the loves backwards starting
// at the oldest one.
offset := math.MaxInt32
perPage := MaxItemsPerGet
defer close(results)
defer close(progress)
p := models.Progress{Total: int64(perPage)}
out:
for {
result, err := b.client.UserTracks(offset, perPage)
if err != nil {
progress <- p.Complete()
results <- models.LovesResult{Error: err}
return
}
// The offset was higher then the actual number of tracks. Adjust the offset
// and continue.
if offset >= result.Total {
p.Total = int64(result.Total)
offset = result.Total - perPage
if offset < 0 {
offset = 0
}
continue
}
count := len(result.Items)
if count == 0 {
break out
}
loves := make(models.LovesList, 0, perPage)
for _, track := range result.Items {
love := track.ToLove()
if love.Created.Unix() > oldestTimestamp.Unix() {
p.Elapsed += 1
loves = append(loves, love)
} else {
break
}
}
sort.Sort(loves)
results <- models.LovesResult{Loves: loves}
progress <- p
if offset <= 0 {
// This was the last request, no further results
break out
}
offset -= perPage
if offset < 0 {
offset = 0
}
}
progress <- p.Complete()
}
func (l Listen) ToListen() models.Listen {
track := l.Track
listenedAt, _ := time.Parse(time.RFC3339, l.PlayedAt)
listen := models.Listen{
Track: models.Track{
TrackName: track.Name,
ReleaseName: track.Album.Name,
ArtistNames: make([]string, 0, len(track.Artists)),
Duration: time.Duration(track.DurationMs * int(time.Millisecond)),
TrackNumber: track.TrackNumber,
Isrc: track.ExternalIds.ISRC,
AdditionalInfo: map[string]any{},
},
}
listen.ListenedAt, _ = time.Parse(time.RFC3339, l.PlayedAt)
for _, artist := range track.Artists {
listen.Track.ArtistNames = append(listen.Track.ArtistNames, artist.Name)
}
info := listen.AdditionalInfo
if !l.Track.IsLocal {
info["music_service"] = "spotify.com"
}
if track.ExternalUrls.Spotify != "" {
info["origin_url"] = track.ExternalUrls.Spotify
info["spotify_id"] = track.ExternalUrls.Spotify
}
if track.Album.ExternalUrls.Spotify != "" {
info["spotify_album_id"] = track.Album.ExternalUrls.Spotify
}
if len(track.Artists) > 0 {
info["spotify_artist_ids"] = extractArtistIds(track.Artists)
}
if len(track.Album.Artists) > 0 {
info["spotify_album_artist_ids"] = extractArtistIds(track.Album.Artists)
ListenedAt: listenedAt,
Track: l.Track.ToTrack(),
}
return listen
}
func (t SavedTrack) ToLove() models.Love {
addedAt, _ := time.Parse(time.RFC3339, t.AddedAt)
love := models.Love{
Created: addedAt,
Track: t.Track.ToTrack(),
}
return love
}
func (t Track) ToTrack() models.Track {
track := models.Track{
TrackName: t.Name,
ReleaseName: t.Album.Name,
ArtistNames: make([]string, 0, len(t.Artists)),
Duration: time.Duration(t.DurationMs * int(time.Millisecond)),
TrackNumber: t.TrackNumber,
Isrc: t.ExternalIds.ISRC,
AdditionalInfo: map[string]any{},
}
for _, artist := range t.Artists {
track.ArtistNames = append(track.ArtistNames, artist.Name)
}
info := track.AdditionalInfo
if !t.IsLocal {
info["music_service"] = "spotify.com"
}
if t.ExternalUrls.Spotify != "" {
info["origin_url"] = t.ExternalUrls.Spotify
info["spotify_id"] = t.ExternalUrls.Spotify
}
if t.Album.ExternalUrls.Spotify != "" {
info["spotify_album_id"] = t.Album.ExternalUrls.Spotify
}
if len(t.Artists) > 0 {
info["spotify_artist_ids"] = extractArtistIds(t.Artists)
}
if len(t.Album.Artists) > 0 {
info["spotify_album_artist_ids"] = extractArtistIds(t.Album.Artists)
}
return track
}
func extractArtistIds(artists []Artist) []string {
artistIds := make([]string, len(artists))
for i, artist := range artists {