diff --git a/server/jellyfin/dto/mappers.go b/server/jellyfin/dto/mappers.go index 4d1a53d68..fb6fd7cf0 100644 --- a/server/jellyfin/dto/mappers.go +++ b/server/jellyfin/dto/mappers.go @@ -1,6 +1,10 @@ package dto -import "github.com/navidrome/navidrome/model" +import ( + "time" + + "github.com/navidrome/navidrome/model" +) func TicksFromSeconds(sec float32) int64 { return int64(float64(sec) * 1e7) } @@ -18,6 +22,10 @@ func UserData(a model.Annotations, itemID string) *UserItemDataDto { r := float64(a.Rating) * 2 // Navidrome 0-5 -> Jellyfin 0-10 d.Rating = &r } + if a.PlayDate != nil { + s := a.PlayDate.UTC().Format(time.RFC3339) + d.LastPlayedDate = &s + } return d } @@ -34,8 +42,6 @@ func SongToBaseItem(mf model.MediaFile) BaseItemDto { AlbumArtist: mf.AlbumArtist, Artists: []string{mf.Artist}, RunTimeTicks: TicksFromSeconds(mf.Duration), - IndexNumber: intPtr(mf.TrackNumber), - ParentIndexNumber: intPtr(mf.DiscNumber), Container: mf.Suffix, CanDownload: true, BackdropImageTags: []string{}, @@ -44,6 +50,12 @@ func SongToBaseItem(mf model.MediaFile) BaseItemDto { if mf.Year > 0 { item.ProductionYear = intPtr(mf.Year) } + if mf.TrackNumber > 0 { + item.IndexNumber = intPtr(mf.TrackNumber) + } + if mf.DiscNumber > 0 { + item.ParentIndexNumber = intPtr(mf.DiscNumber) + } if len(mf.Genres) > 0 { for _, g := range mf.Genres { item.Genres = append(item.Genres, g.Name) diff --git a/server/jellyfin/dto/mappers_test.go b/server/jellyfin/dto/mappers_test.go index 1f076aac4..41a397a83 100644 --- a/server/jellyfin/dto/mappers_test.go +++ b/server/jellyfin/dto/mappers_test.go @@ -1,6 +1,8 @@ package dto import ( + "time" + "github.com/navidrome/navidrome/model" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -28,6 +30,29 @@ var _ = Describe("mappers", func() { Expect(item.UserData.Played).To(BeTrue()) }) + It("omits IndexNumber and ParentIndexNumber when track/disc numbers are untagged", func() { + mf := model.MediaFile{ + ID: "song-2", Title: "Song", Album: "Alb", AlbumID: "alb-1", + Artist: "Art", AlbumArtist: "AA", TrackNumber: 0, DiscNumber: 0, + Duration: 60, + } + item := SongToBaseItem(mf) + Expect(item.IndexNumber).To(BeNil()) + Expect(item.ParentIndexNumber).To(BeNil()) + }) + + It("maps PlayDate to UserData.LastPlayedDate", func() { + playDate := time.Date(2023, 5, 17, 12, 30, 0, 0, time.UTC) + mf := model.MediaFile{ + ID: "song-3", Title: "Song", Album: "Alb", AlbumID: "alb-1", + Artist: "Art", AlbumArtist: "AA", Duration: 60, + } + mf.PlayDate = &playDate + item := SongToBaseItem(mf) + Expect(item.UserData.LastPlayedDate).NotTo(BeNil()) + Expect(*item.UserData.LastPlayedDate).To(Equal(playDate.Format(time.RFC3339))) + }) + It("maps an album to a MusicAlbum folder item", func() { al := model.Album{ID: "alb-1", Name: "Alb", AlbumArtist: "AA", AlbumArtistID: "art-1", MaxYear: 1999, SongCount: 10} item := AlbumToBaseItem(al)