diff --git a/backends/funkwhale/funkwhale.go b/backends/funkwhale/funkwhale.go index 708f2f9..604c697 100644 --- a/backends/funkwhale/funkwhale.go +++ b/backends/funkwhale/funkwhale.go @@ -66,7 +66,7 @@ out: } for _, fwListen := range result.Results { - listen := fwListen.ToListen() + listen := fwListen.AsListen() if listen.ListenedAt.Unix() > oldestTimestamp.Unix() { p.Elapsed += 1 listens = append(listens, listen) @@ -118,7 +118,7 @@ out: } for _, favorite := range result.Results { - love := favorite.ToLove() + love := favorite.AsLove() if love.Created.Unix() > oldestTimestamp.Unix() { p.Elapsed += 1 loves = append(loves, love) @@ -142,24 +142,10 @@ out: results <- models.LovesResult{Loves: loves} } -func (l Listening) ToListen() models.Listen { - track := l.Track +func (l Listening) AsListen() models.Listen { listen := models.Listen{ UserName: l.User.UserName, - Track: models.Track{ - TrackName: track.Title, - ReleaseName: track.Album.Title, - ArtistNames: []string{track.Artist.Name}, - TrackNumber: track.Position, - DiscNumber: track.DiscNumber, - RecordingMbid: models.MBID(track.RecordingMbid), - ReleaseMbid: models.MBID(track.Album.ReleaseMbid), - ArtistMbids: []models.MBID{models.MBID(track.Artist.ArtistMbid)}, - Tags: track.Tags, - AdditionalInfo: map[string]any{ - "media_player": FunkwhaleClientName, - }, - }, + Track: l.Track.AsTrack(), } listenedAt, err := time.Parse(time.RFC3339, l.CreationDate) @@ -167,33 +153,15 @@ func (l Listening) ToListen() models.Listen { listen.ListenedAt = listenedAt } - if len(track.Uploads) > 0 { - listen.Track.Duration = time.Duration(track.Uploads[0].Duration * int(time.Second)) - } - return listen } -func (f FavoriteTrack) ToLove() models.Love { - track := f.Track - recordingMbid := models.MBID(track.RecordingMbid) +func (f FavoriteTrack) AsLove() models.Love { + track := f.Track.AsTrack() love := models.Love{ UserName: f.User.UserName, - RecordingMbid: recordingMbid, - Track: models.Track{ - TrackName: track.Title, - ReleaseName: track.Album.Title, - ArtistNames: []string{track.Artist.Name}, - TrackNumber: track.Position, - DiscNumber: track.DiscNumber, - RecordingMbid: recordingMbid, - ReleaseMbid: models.MBID(track.Album.ReleaseMbid), - ArtistMbids: []models.MBID{models.MBID(track.Artist.ArtistMbid)}, - Tags: track.Tags, - AdditionalInfo: map[string]any{ - "media_player": FunkwhaleClientName, - }, - }, + RecordingMbid: track.RecordingMbid, + Track: track, } created, err := time.Parse(time.RFC3339, f.CreationDate) @@ -201,9 +169,29 @@ func (f FavoriteTrack) ToLove() models.Love { love.Created = created } - if len(track.Uploads) > 0 { - love.Track.Duration = time.Duration(track.Uploads[0].Duration * int(time.Second)) - } - return love } + +func (t Track) AsTrack() models.Track { + recordingMbid := models.MBID(t.RecordingMbid) + track := models.Track{ + TrackName: t.Title, + ReleaseName: t.Album.Title, + ArtistNames: []string{t.Artist.Name}, + TrackNumber: t.Position, + DiscNumber: t.DiscNumber, + RecordingMbid: recordingMbid, + ReleaseMbid: models.MBID(t.Album.ReleaseMbid), + ArtistMbids: []models.MBID{models.MBID(t.Artist.ArtistMbid)}, + Tags: t.Tags, + AdditionalInfo: map[string]any{ + "media_player": FunkwhaleClientName, + }, + } + + if len(t.Uploads) > 0 { + track.Duration = time.Duration(t.Uploads[0].Duration * int(time.Second)) + } + + return track +} diff --git a/backends/funkwhale/funkwhale_test.go b/backends/funkwhale/funkwhale_test.go index a548c3c..3047d43 100644 --- a/backends/funkwhale/funkwhale_test.go +++ b/backends/funkwhale/funkwhale_test.go @@ -34,7 +34,7 @@ func TestFromConfig(t *testing.T) { assert.IsType(t, &funkwhale.FunkwhaleApiBackend{}, backend) } -func TestFunkwhaleListeningToListen(t *testing.T) { +func TestFunkwhaleListeningAsListen(t *testing.T) { fwListen := funkwhale.Listening{ CreationDate: "2023-11-09T23:59:29.022005Z", User: funkwhale.User{ @@ -61,7 +61,7 @@ func TestFunkwhaleListeningToListen(t *testing.T) { }, }, } - listen := fwListen.ToListen() + listen := fwListen.AsListen() assert := assert.New(t) assert.Equal(time.Unix(1699574369, 0).Unix(), listen.ListenedAt.Unix()) assert.Equal(fwListen.User.UserName, listen.UserName) @@ -79,7 +79,7 @@ func TestFunkwhaleListeningToListen(t *testing.T) { assert.Equal(funkwhale.FunkwhaleClientName, listen.AdditionalInfo["media_player"]) } -func TestFunkwhaleFavoriteTrackToLove(t *testing.T) { +func TestFunkwhaleFavoriteTrackAsLove(t *testing.T) { favorite := funkwhale.FavoriteTrack{ CreationDate: "2023-11-09T23:59:29.022005Z", User: funkwhale.User{ @@ -106,7 +106,7 @@ func TestFunkwhaleFavoriteTrackToLove(t *testing.T) { }, }, } - love := favorite.ToLove() + love := favorite.AsLove() assert := assert.New(t) assert.Equal(time.Unix(1699574369, 0).Unix(), love.Created.Unix()) assert.Equal(favorite.User.UserName, love.UserName) diff --git a/backends/jspf/jspf.go b/backends/jspf/jspf.go index 7296d4b..99cb59a 100644 --- a/backends/jspf/jspf.go +++ b/backends/jspf/jspf.go @@ -53,7 +53,7 @@ func (b *JspfBackend) FinishImport() error { func (b *JspfBackend) ImportLoves(export models.LovesResult, importResult models.ImportResult, progress chan models.Progress) (models.ImportResult, error) { for _, love := range export.Loves { - track := loveToTrack(love) + track := loveAsTrack(love) b.tracks = append(b.tracks, track) importResult.ImportCount += 1 importResult.UpdateTimestamp(love.Created) @@ -63,7 +63,7 @@ func (b *JspfBackend) ImportLoves(export models.LovesResult, importResult models return importResult, nil } -func loveToTrack(love models.Love) Track { +func loveAsTrack(love models.Love) Track { extension := MusicBrainzTrackExtension{ AddedAt: love.Created, AddedBy: love.UserName, diff --git a/backends/listenbrainz/listenbrainz.go b/backends/listenbrainz/listenbrainz.go index e773929..e4b35b9 100644 --- a/backends/listenbrainz/listenbrainz.go +++ b/backends/listenbrainz/listenbrainz.go @@ -77,7 +77,7 @@ out: for _, listen := range result.Payload.Listens { if listen.ListenedAt > oldestTimestamp.Unix() { - listens = append(listens, listen.ToListen()) + listens = append(listens, listen.AsListen()) } else { // result contains listens older then oldestTimestamp, // we can stop requesting more @@ -117,7 +117,7 @@ out: } for _, feedback := range result.Feedback { - love := feedback.ToLove() + love := feedback.AsLove() if love.Created.Unix() > oldestTimestamp.Unix() { loves = append(loves, love) p.Elapsed += 1 @@ -196,53 +196,55 @@ func (b *ListenBrainzApiBackend) ImportLoves(export models.LovesResult, importRe return importResult, nil } -func (lbListen Listen) ToListen() models.Listen { - track := lbListen.TrackMetadata +func (lbListen Listen) AsListen() models.Listen { listen := models.Listen{ ListenedAt: time.Unix(lbListen.ListenedAt, 0), UserName: lbListen.UserName, - Track: models.Track{ - TrackName: track.TrackName, - ReleaseName: track.ReleaseName, - ArtistNames: []string{track.ArtistName}, - Duration: track.Duration(), - TrackNumber: track.TrackNumber(), - DiscNumber: track.DiscNumber(), - RecordingMbid: models.MBID(track.RecordingMbid()), - ReleaseMbid: models.MBID(track.ReleaseMbid()), - ReleaseGroupMbid: models.MBID(track.ReleaseGroupMbid()), - Isrc: track.Isrc(), - AdditionalInfo: track.AdditionalInfo, - }, + Track: lbListen.TrackMetadata.AsTrack(), } return listen } -func (f Feedback) ToLove() models.Love { - track := f.TrackMetadata +func (f Feedback) AsLove() models.Love { recordingMbid := models.MBID(f.RecordingMbid) + track := f.TrackMetadata + if track == nil { + track = &Track{} + } love := models.Love{ UserName: f.UserName, RecordingMbid: recordingMbid, Created: time.Unix(f.Created, 0), - Track: models.Track{ - RecordingMbid: recordingMbid, - }, + Track: track.AsTrack(), } - if track != nil { - love.Track.TrackName = track.TrackName - love.Track.ReleaseName = track.ReleaseName - love.ArtistNames = []string{track.ArtistName} - love.ReleaseMbid = models.MBID(track.MbidMapping.ReleaseMbid) - love.ArtistMbids = make([]models.MBID, 0, len(track.MbidMapping.ArtistMbids)) - - if track.MbidMapping != nil { - for _, artistMbid := range track.MbidMapping.ArtistMbids { - love.Track.ArtistMbids = append(love.Track.ArtistMbids, models.MBID(artistMbid)) - } - } + if love.Track.RecordingMbid == "" { + love.Track.RecordingMbid = love.RecordingMbid } return love } + +func (t Track) AsTrack() models.Track { + track := models.Track{ + TrackName: t.TrackName, + ReleaseName: t.ReleaseName, + ArtistNames: []string{t.ArtistName}, + Duration: t.Duration(), + TrackNumber: t.TrackNumber(), + DiscNumber: t.DiscNumber(), + RecordingMbid: models.MBID(t.RecordingMbid()), + ReleaseMbid: models.MBID(t.ReleaseMbid()), + ReleaseGroupMbid: models.MBID(t.ReleaseGroupMbid()), + Isrc: t.Isrc(), + AdditionalInfo: t.AdditionalInfo, + } + + if t.MbidMapping != nil && len(track.ArtistMbids) == 0 { + for _, artistMbid := range t.MbidMapping.ArtistMbids { + track.ArtistMbids = append(track.ArtistMbids, models.MBID(artistMbid)) + } + } + + return track +} diff --git a/backends/listenbrainz/listenbrainz_test.go b/backends/listenbrainz/listenbrainz_test.go index 507c89f..ae8373c 100644 --- a/backends/listenbrainz/listenbrainz_test.go +++ b/backends/listenbrainz/listenbrainz_test.go @@ -34,7 +34,7 @@ func TestFromConfig(t *testing.T) { assert.IsType(t, &listenbrainz.ListenBrainzApiBackend{}, backend) } -func TestListenBrainzListenToListen(t *testing.T) { +func TestListenBrainzListenAsListen(t *testing.T) { lbListen := listenbrainz.Listen{ ListenedAt: 1699289873, UserName: "outsidecontext", @@ -54,7 +54,7 @@ func TestListenBrainzListenToListen(t *testing.T) { }, }, } - listen := lbListen.ToListen() + listen := lbListen.AsListen() assert.Equal(t, time.Unix(1699289873, 0), listen.ListenedAt) assert.Equal(t, lbListen.UserName, listen.UserName) assert.Equal(t, time.Duration(413787*time.Millisecond), listen.Duration) @@ -70,7 +70,7 @@ func TestListenBrainzListenToListen(t *testing.T) { assert.Equal(t, lbListen.TrackMetadata.AdditionalInfo["foo"], listen.AdditionalInfo["foo"]) } -func TestListenBrainzFeedbackToLove(t *testing.T) { +func TestListenBrainzFeedbackAsLove(t *testing.T) { recordingMbid := "c0a1fc94-5f04-4a5f-bc09-e5de0c49cd12" releaseMbid := "d7f22677-9803-4d21-ba42-081b633a6f68" artistMbid := "d7f22677-9803-4d21-ba42-081b633a6f68" @@ -90,7 +90,7 @@ func TestListenBrainzFeedbackToLove(t *testing.T) { }, }, } - love := feedback.ToLove() + love := feedback.AsLove() assert := assert.New(t) assert.Equal(time.Unix(1699859066, 0).Unix(), love.Created.Unix()) assert.Equal(feedback.UserName, love.UserName) @@ -104,14 +104,14 @@ func TestListenBrainzFeedbackToLove(t *testing.T) { assert.Equal(models.MBID(artistMbid), love.Track.ArtistMbids[0]) } -func TestListenBrainzPartialFeedbackToLove(t *testing.T) { +func TestListenBrainzPartialFeedbackAsLove(t *testing.T) { recordingMbid := "c0a1fc94-5f04-4a5f-bc09-e5de0c49cd12" feedback := listenbrainz.Feedback{ Created: 1699859066, RecordingMbid: recordingMbid, Score: 1, } - love := feedback.ToLove() + love := feedback.AsLove() assert := assert.New(t) assert.Equal(time.Unix(1699859066, 0).Unix(), love.Created.Unix()) assert.Equal(models.MBID(recordingMbid), love.RecordingMbid) diff --git a/backends/listenbrainz/models.go b/backends/listenbrainz/models.go index 2af9d72..ee00ad9 100644 --- a/backends/listenbrainz/models.go +++ b/backends/listenbrainz/models.go @@ -149,11 +149,21 @@ func (t Track) Isrc() string { } func (t Track) RecordingMbid() string { - return tryGetValueOrEmpty[string](t.AdditionalInfo, "recording_mbid") + mbid := tryGetValueOrEmpty[string](t.AdditionalInfo, "recording_mbid") + if mbid == "" && t.MbidMapping != nil { + return t.MbidMapping.RecordingMbid + } else { + return mbid + } } func (t Track) ReleaseMbid() string { - return tryGetValueOrEmpty[string](t.AdditionalInfo, "release_mbid") + mbid := tryGetValueOrEmpty[string](t.AdditionalInfo, "release_mbid") + if mbid == "" && t.MbidMapping != nil { + return t.MbidMapping.ReleaseMbid + } else { + return mbid + } } func (t Track) ReleaseGroupMbid() string { diff --git a/backends/maloja/maloja.go b/backends/maloja/maloja.go index 8f1a850..9c2c4fe 100644 --- a/backends/maloja/maloja.go +++ b/backends/maloja/maloja.go @@ -73,7 +73,7 @@ out: for _, scrobble := range result.List { if scrobble.ListenedAt > oldestTimestamp.Unix() { p.Elapsed += 1 - listens = append(listens, scrobble.ToListen()) + listens = append(listens, scrobble.AsListen()) } else { break out } @@ -116,7 +116,7 @@ func (b *MalojaApiBackend) ImportListens(export models.ListensResult, importResu return importResult, nil } -func (s Scrobble) ToListen() models.Listen { +func (s Scrobble) AsListen() models.Listen { track := s.Track listen := models.Listen{ ListenedAt: time.Unix(s.ListenedAt, 0), diff --git a/backends/maloja/maloja_test.go b/backends/maloja/maloja_test.go index 809b19a..79dccb0 100644 --- a/backends/maloja/maloja_test.go +++ b/backends/maloja/maloja_test.go @@ -32,7 +32,7 @@ func TestFromConfig(t *testing.T) { assert.IsType(t, &maloja.MalojaApiBackend{}, backend) } -func TestScrobbleToListen(t *testing.T) { +func TestScrobbleAsListen(t *testing.T) { scrobble := maloja.Scrobble{ ListenedAt: 1699289873, Track: maloja.Track{ @@ -45,7 +45,7 @@ func TestScrobbleToListen(t *testing.T) { }, Origin: "client:Funkwhale", } - listen := scrobble.ToListen() + listen := scrobble.AsListen() assert := assert.New(t) assert.Equal(time.Unix(1699289873, 0), listen.ListenedAt) assert.Equal(time.Duration(414*time.Second), listen.Duration) diff --git a/backends/spotify/spotify.go b/backends/spotify/spotify.go index 0362d30..7ce325f 100644 --- a/backends/spotify/spotify.go +++ b/backends/spotify/spotify.go @@ -108,7 +108,7 @@ func (b *SpotifyApiBackend) ExportListens(oldestTimestamp time.Time, results cha listens := make(models.ListensList, 0, len(result.Items)) for _, listen := range result.Items { - l := listen.ToListen() + l := listen.AsListen() if l.ListenedAt.Unix() > oldestTimestamp.Unix() { listens = append(listens, l) } else { @@ -168,7 +168,7 @@ out: loves := make(models.LovesList, 0, perPage) for _, track := range result.Items { - love := track.ToLove() + love := track.AsLove() if love.Created.Unix() > oldestTimestamp.Unix() { loves = append(loves, love) } else { @@ -196,27 +196,27 @@ out: progress <- p.Complete() } -func (l Listen) ToListen() models.Listen { +func (l Listen) AsListen() models.Listen { listenedAt, _ := time.Parse(time.RFC3339, l.PlayedAt) listen := models.Listen{ ListenedAt: listenedAt, - Track: l.Track.ToTrack(), + Track: l.Track.AsTrack(), } return listen } -func (t SavedTrack) ToLove() models.Love { +func (t SavedTrack) AsLove() models.Love { addedAt, _ := time.Parse(time.RFC3339, t.AddedAt) love := models.Love{ Created: addedAt, - Track: t.Track.ToTrack(), + Track: t.Track.AsTrack(), } return love } -func (t Track) ToTrack() models.Track { +func (t Track) AsTrack() models.Track { track := models.Track{ TrackName: t.Name, ReleaseName: t.Album.Name, diff --git a/backends/spotify/spotify_test.go b/backends/spotify/spotify_test.go index 8872e83..6ca4eab 100644 --- a/backends/spotify/spotify_test.go +++ b/backends/spotify/spotify_test.go @@ -28,13 +28,13 @@ import ( "go.uploadedlobster.com/scotty/backends/spotify" ) -func TestSpotifyListenToListen(t *testing.T) { +func TestSpotifyListenAsListen(t *testing.T) { data, err := os.ReadFile("testdata/listen.json") require.NoError(t, err) spListen := spotify.Listen{} err = json.Unmarshal(data, &spListen) require.NoError(t, err) - listen := spListen.ToListen() + listen := spListen.AsListen() listenedAt, _ := time.Parse(time.RFC3339, "2023-11-21T15:24:33.361Z") assert.Equal(t, listenedAt, listen.ListenedAt) assert.Equal(t, time.Duration(413826*time.Millisecond), listen.Duration) @@ -53,13 +53,13 @@ func TestSpotifyListenToListen(t *testing.T) { assert.Equal(t, []string{"https://open.spotify.com/artist/101HSR6JTJqe3DBh6rb8kz"}, info["spotify_album_artist_ids"]) } -func TestSavedTrackToLove(t *testing.T) { +func TestSavedTrackAsLove(t *testing.T) { data, err := os.ReadFile("testdata/track.json") require.NoError(t, err) track := spotify.SavedTrack{} err = json.Unmarshal(data, &track) require.NoError(t, err) - love := track.ToLove() + love := track.AsLove() created, _ := time.Parse(time.RFC3339, "2022-02-13T21:46:08Z") assert.Equal(t, created, love.Created) assert.Equal(t, time.Duration(187680*time.Millisecond), love.Duration)