diff --git a/conf/configuration.go b/conf/configuration.go index a7eff2d3..6822a1a9 100644 --- a/conf/configuration.go +++ b/conf/configuration.go @@ -153,6 +153,7 @@ type subsonicOptions struct { ArtistParticipations bool DefaultReportRealPath bool LegacyClients string + MinimalClients string } type TagConf struct { diff --git a/server/subsonic/helpers.go b/server/subsonic/helpers.go index 3cf5ae6b..2303914d 100644 --- a/server/subsonic/helpers.go +++ b/server/subsonic/helpers.go @@ -166,11 +166,30 @@ func getTranscoding(ctx context.Context) (format string, bitRate int) { return } +func isClientInList(clientList, client string) bool { + if clientList == "" || client == "" { + return false + } + clients := strings.Split(clientList, ",") + for _, c := range clients { + if strings.TrimSpace(c) == client { + return true + } + } + return false +} + func childFromMediaFile(ctx context.Context, mf model.MediaFile) responses.Child { child := responses.Child{} child.Id = mf.ID child.Title = mf.FullTitle() child.IsDir = false + + player, ok := request.PlayerFrom(ctx) + if ok && isClientInList(conf.Server.Subsonic.MinimalClients, player.Client) { + return child + } + child.Parent = mf.AlbumID child.Album = mf.Album child.Year = int32(mf.Year) @@ -183,7 +202,7 @@ func childFromMediaFile(ctx context.Context, mf model.MediaFile) responses.Child child.BitRate = int32(mf.BitRate) child.CoverArt = mf.CoverArtID().String() child.ContentType = mf.ContentType() - player, ok := request.PlayerFrom(ctx) + if ok && player.ReportRealPath { child.Path = mf.AbsolutePath() } else { @@ -211,8 +230,8 @@ func childFromMediaFile(ctx context.Context, mf model.MediaFile) responses.Child } func osChildFromMediaFile(ctx context.Context, mf model.MediaFile) *responses.OpenSubsonicChild { - player, _ := request.PlayerFrom(ctx) - if strings.Contains(conf.Server.Subsonic.LegacyClients, player.Client) { + player, ok := request.PlayerFrom(ctx) + if ok && isClientInList(conf.Server.Subsonic.MinimalClients, player.Client) { return nil } child := responses.OpenSubsonicChild{} diff --git a/server/subsonic/helpers_test.go b/server/subsonic/helpers_test.go index a6508d4b..2a5f4376 100644 --- a/server/subsonic/helpers_test.go +++ b/server/subsonic/helpers_test.go @@ -169,6 +169,190 @@ var _ = Describe("helpers", func() { }) }) + DescribeTable("isClientInList", + func(list, client string, expected bool) { + Expect(isClientInList(list, client)).To(Equal(expected)) + }, + Entry("returns false when clientList is empty", "", "some-client", false), + Entry("returns false when client is empty", "client1,client2", "", false), + Entry("returns false when both are empty", "", "", false), + Entry("returns true when client matches single entry", "my-client", "my-client", true), + Entry("returns true when client matches first in list", "client1,client2,client3", "client1", true), + Entry("returns true when client matches middle in list", "client1,client2,client3", "client2", true), + Entry("returns true when client matches last in list", "client1,client2,client3", "client3", true), + Entry("returns false when client does not match", "client1,client2", "client3", false), + Entry("trims whitespace from client list entries", "client1, client2 , client3", "client2", true), + Entry("does not trim the client parameter", "client1,client2", " client1", false), + ) + + Describe("childFromMediaFile", func() { + var mf model.MediaFile + var ctx context.Context + + BeforeEach(func() { + mf = model.MediaFile{ + ID: "mf-1", + Title: "Test Song", + Album: "Test Album", + AlbumID: "album-1", + Artist: "Test Artist", + ArtistID: "artist-1", + Year: 2023, + Genre: "Rock", + TrackNumber: 5, + Duration: 180.5, + Size: 5000000, + Suffix: "mp3", + BitRate: 320, + } + ctx = context.Background() + }) + + Context("with minimal client", func() { + BeforeEach(func() { + conf.Server.Subsonic.MinimalClients = "minimal-client" + player := model.Player{Client: "minimal-client"} + ctx = request.WithPlayer(ctx, player) + }) + + It("returns only basic fields", func() { + child := childFromMediaFile(ctx, mf) + Expect(child.Id).To(Equal("mf-1")) + Expect(child.Title).To(Equal("Test Song")) + Expect(child.IsDir).To(BeFalse()) + + // These should not be set + Expect(child.Album).To(BeEmpty()) + Expect(child.Artist).To(BeEmpty()) + Expect(child.Parent).To(BeEmpty()) + Expect(child.Year).To(BeZero()) + Expect(child.Genre).To(BeEmpty()) + Expect(child.Track).To(BeZero()) + Expect(child.Duration).To(BeZero()) + Expect(child.Size).To(BeZero()) + Expect(child.Suffix).To(BeEmpty()) + Expect(child.BitRate).To(BeZero()) + Expect(child.CoverArt).To(BeEmpty()) + Expect(child.ContentType).To(BeEmpty()) + Expect(child.Path).To(BeEmpty()) + }) + + It("does not include OpenSubsonic extension", func() { + child := childFromMediaFile(ctx, mf) + Expect(child.OpenSubsonicChild).To(BeNil()) + }) + }) + + Context("with non-minimal client", func() { + BeforeEach(func() { + conf.Server.Subsonic.MinimalClients = "minimal-client" + player := model.Player{Client: "regular-client"} + ctx = request.WithPlayer(ctx, player) + }) + + It("returns all fields", func() { + child := childFromMediaFile(ctx, mf) + Expect(child.Id).To(Equal("mf-1")) + Expect(child.Title).To(Equal("Test Song")) + Expect(child.IsDir).To(BeFalse()) + Expect(child.Album).To(Equal("Test Album")) + Expect(child.Artist).To(Equal("Test Artist")) + Expect(child.Parent).To(Equal("album-1")) + Expect(child.Year).To(Equal(int32(2023))) + Expect(child.Genre).To(Equal("Rock")) + Expect(child.Track).To(Equal(int32(5))) + Expect(child.Duration).To(Equal(int32(180))) + Expect(child.Size).To(Equal(int64(5000000))) + Expect(child.Suffix).To(Equal("mp3")) + Expect(child.BitRate).To(Equal(int32(320))) + }) + }) + + Context("when minimal clients list is empty", func() { + BeforeEach(func() { + conf.Server.Subsonic.MinimalClients = "" + player := model.Player{Client: "any-client"} + ctx = request.WithPlayer(ctx, player) + }) + + It("returns all fields", func() { + child := childFromMediaFile(ctx, mf) + Expect(child.Album).To(Equal("Test Album")) + Expect(child.Artist).To(Equal("Test Artist")) + }) + }) + + Context("when no player in context", func() { + It("returns all fields", func() { + child := childFromMediaFile(ctx, mf) + Expect(child.Album).To(Equal("Test Album")) + Expect(child.Artist).To(Equal("Test Artist")) + }) + }) + }) + + Describe("osChildFromMediaFile", func() { + var mf model.MediaFile + var ctx context.Context + + BeforeEach(func() { + mf = model.MediaFile{ + ID: "mf-1", + Title: "Test Song", + Artist: "Test Artist", + Comment: "Test Comment", + } + ctx = context.Background() + }) + + Context("with minimal client", func() { + BeforeEach(func() { + conf.Server.Subsonic.MinimalClients = "minimal-client" + player := model.Player{Client: "minimal-client"} + ctx = request.WithPlayer(ctx, player) + }) + + It("returns nil", func() { + osChild := osChildFromMediaFile(ctx, mf) + Expect(osChild).To(BeNil()) + }) + }) + + Context("with non-minimal client", func() { + BeforeEach(func() { + conf.Server.Subsonic.MinimalClients = "minimal-client" + player := model.Player{Client: "regular-client"} + ctx = request.WithPlayer(ctx, player) + }) + + It("returns OpenSubsonic child fields", func() { + osChild := osChildFromMediaFile(ctx, mf) + Expect(osChild).ToNot(BeNil()) + Expect(osChild.Comment).To(Equal("Test Comment")) + }) + }) + + Context("when minimal clients list is empty", func() { + BeforeEach(func() { + conf.Server.Subsonic.MinimalClients = "" + player := model.Player{Client: "any-client"} + ctx = request.WithPlayer(ctx, player) + }) + + It("returns OpenSubsonic child fields", func() { + osChild := osChildFromMediaFile(ctx, mf) + Expect(osChild).ToNot(BeNil()) + }) + }) + + Context("when no player in context", func() { + It("returns OpenSubsonic child fields", func() { + osChild := osChildFromMediaFile(ctx, mf) + Expect(osChild).ToNot(BeNil()) + }) + }) + }) + Describe("selectedMusicFolderIds", func() { var user model.User var ctx context.Context diff --git a/server/subsonic/playlists.go b/server/subsonic/playlists.go index 23fac681..fbf9deb9 100644 --- a/server/subsonic/playlists.go +++ b/server/subsonic/playlists.go @@ -7,8 +7,10 @@ import ( "net/http" "time" + "github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" + "github.com/navidrome/navidrome/model/request" "github.com/navidrome/navidrome/server/subsonic/responses" "github.com/navidrome/navidrome/utils/req" "github.com/navidrome/navidrome/utils/slice" @@ -23,7 +25,7 @@ func (api *Router) GetPlaylists(r *http.Request) (*responses.Subsonic, error) { } response := newResponse() response.Playlists = &responses.Playlists{ - Playlist: slice.Map(allPls, api.buildPlaylist), + Playlist: slice.MapWithArg(allPls, ctx, api.buildPlaylist), } return response, nil } @@ -51,7 +53,7 @@ func (api *Router) getPlaylist(ctx context.Context, id string) (*responses.Subso response := newResponse() response.Playlist = &responses.PlaylistWithSongs{ - Playlist: api.buildPlaylist(*pls), + Playlist: api.buildPlaylist(ctx, *pls), } response.Playlist.Entry = slice.MapWithArg(pls.MediaFiles(), ctx, childFromMediaFile) return response, nil @@ -152,21 +154,28 @@ func (api *Router) UpdatePlaylist(r *http.Request) (*responses.Subsonic, error) return newResponse(), nil } -func (api *Router) buildPlaylist(p model.Playlist) responses.Playlist { +func (api *Router) buildPlaylist(ctx context.Context, p model.Playlist) responses.Playlist { pls := responses.Playlist{} pls.Id = p.ID pls.Name = p.Name - pls.Comment = p.Comment pls.SongCount = int32(p.SongCount) - pls.Owner = p.OwnerName pls.Duration = int32(p.Duration) - pls.Public = p.Public pls.Created = p.CreatedAt - pls.CoverArt = p.CoverArtID().String() if p.IsSmartPlaylist() { pls.Changed = time.Now() } else { pls.Changed = p.UpdatedAt } + + player, ok := request.PlayerFrom(ctx) + if ok && isClientInList(conf.Server.Subsonic.MinimalClients, player.Client) { + return pls + } + + pls.Comment = p.Comment + pls.Owner = p.OwnerName + pls.Public = p.Public + pls.CoverArt = p.CoverArtID().String() + return pls } diff --git a/server/subsonic/playlists_test.go b/server/subsonic/playlists_test.go index c0a007d6..20da12dd 100644 --- a/server/subsonic/playlists_test.go +++ b/server/subsonic/playlists_test.go @@ -2,9 +2,12 @@ package subsonic import ( "context" + "time" + "github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/core" "github.com/navidrome/navidrome/model" + "github.com/navidrome/navidrome/model/request" "github.com/navidrome/navidrome/tests" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -12,6 +15,108 @@ import ( var _ core.Playlists = (*fakePlaylists)(nil) +var _ = Describe("buildPlaylist", func() { + var router *Router + var ds model.DataStore + var ctx context.Context + var playlist model.Playlist + + BeforeEach(func() { + ds = &tests.MockDataStore{} + router = New(ds, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) + ctx = context.Background() + + createdAt := time.Date(2023, 1, 15, 10, 30, 0, 0, time.UTC) + updatedAt := time.Date(2023, 2, 20, 14, 45, 0, 0, time.UTC) + + playlist = model.Playlist{ + ID: "pls-1", + Name: "My Playlist", + Comment: "Test comment", + OwnerName: "admin", + Public: true, + SongCount: 10, + Duration: 600, + CreatedAt: createdAt, + UpdatedAt: updatedAt, + } + }) + + Context("with minimal client", func() { + BeforeEach(func() { + conf.Server.Subsonic.MinimalClients = "minimal-client" + player := model.Player{Client: "minimal-client"} + ctx = request.WithPlayer(ctx, player) + }) + + It("returns only basic fields", func() { + result := router.buildPlaylist(ctx, playlist) + + Expect(result.Id).To(Equal("pls-1")) + Expect(result.Name).To(Equal("My Playlist")) + Expect(result.SongCount).To(Equal(int32(10))) + Expect(result.Duration).To(Equal(int32(600))) + Expect(result.Created).To(Equal(playlist.CreatedAt)) + Expect(result.Changed).To(Equal(playlist.UpdatedAt)) + + // These should not be set + Expect(result.Comment).To(BeEmpty()) + Expect(result.Owner).To(BeEmpty()) + Expect(result.Public).To(BeFalse()) + Expect(result.CoverArt).To(BeEmpty()) + }) + }) + + Context("with non-minimal client", func() { + BeforeEach(func() { + conf.Server.Subsonic.MinimalClients = "minimal-client" + player := model.Player{Client: "regular-client"} + ctx = request.WithPlayer(ctx, player) + }) + + It("returns all fields", func() { + result := router.buildPlaylist(ctx, playlist) + + Expect(result.Id).To(Equal("pls-1")) + Expect(result.Name).To(Equal("My Playlist")) + Expect(result.SongCount).To(Equal(int32(10))) + Expect(result.Duration).To(Equal(int32(600))) + Expect(result.Created).To(Equal(playlist.CreatedAt)) + Expect(result.Changed).To(Equal(playlist.UpdatedAt)) + Expect(result.Comment).To(Equal("Test comment")) + Expect(result.Owner).To(Equal("admin")) + Expect(result.Public).To(BeTrue()) + }) + }) + + Context("when minimal clients list is empty", func() { + BeforeEach(func() { + conf.Server.Subsonic.MinimalClients = "" + player := model.Player{Client: "any-client"} + ctx = request.WithPlayer(ctx, player) + }) + + It("returns all fields", func() { + result := router.buildPlaylist(ctx, playlist) + + Expect(result.Comment).To(Equal("Test comment")) + Expect(result.Owner).To(Equal("admin")) + Expect(result.Public).To(BeTrue()) + }) + }) + + Context("when no player in context", func() { + It("returns all fields", func() { + result := router.buildPlaylist(ctx, playlist) + + Expect(result.Comment).To(Equal("Test comment")) + Expect(result.Owner).To(Equal("admin")) + Expect(result.Public).To(BeTrue()) + }) + }) + +}) + var _ = Describe("UpdatePlaylist", func() { var router *Router var ds model.DataStore diff --git a/server/subsonic/responses/.snapshots/Responses AlbumList with OS data should match .JSON b/server/subsonic/responses/.snapshots/Responses AlbumList with OS data should match .JSON index 0e6425f6..a50603bf 100644 --- a/server/subsonic/responses/.snapshots/Responses AlbumList with OS data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses AlbumList with OS data should match .JSON @@ -9,7 +9,6 @@ { "id": "1", "isDir": false, - "isVideo": false, "bpm": 0, "comment": "", "sortName": "sort name", diff --git a/server/subsonic/responses/.snapshots/Responses AlbumList with OS data should match .XML b/server/subsonic/responses/.snapshots/Responses AlbumList with OS data should match .XML index 07200c0c..45b7033f 100644 --- a/server/subsonic/responses/.snapshots/Responses AlbumList with OS data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses AlbumList with OS data should match .XML @@ -1,6 +1,6 @@ - + mood1 diff --git a/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .JSON b/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .JSON index 94637875..7963b44f 100644 --- a/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .JSON @@ -9,8 +9,7 @@ { "id": "1", "isDir": false, - "title": "title", - "isVideo": false + "title": "title" } ] } diff --git a/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .XML b/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .XML index 000b8c00..693bbfa5 100644 --- a/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .XML @@ -1,5 +1,5 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .JSON b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .JSON index c2a29b22..6ed471e8 100644 --- a/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .JSON @@ -93,7 +93,6 @@ "transcodedSuffix": "mp3", "duration": 146, "bitRate": 320, - "isVideo": false, "bpm": 127, "comment": "a comment", "sortName": "sorted song", @@ -185,7 +184,6 @@ "transcodedSuffix": "mp3", "duration": 146, "bitRate": 320, - "isVideo": false, "bpm": 0, "comment": "", "sortName": "", diff --git a/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .XML b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .XML index 1ad3e600..67dcf6bd 100644 --- a/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .XML @@ -15,7 +15,7 @@ sad - + ISRC-1 @@ -33,7 +33,7 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .JSON index 7ca38d4d..5b3367e7 100644 --- a/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .JSON @@ -10,8 +10,7 @@ "entry": { "id": "1", "isDir": false, - "title": "title", - "isVideo": false + "title": "title" }, "position": 123, "username": "user2", diff --git a/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .XML b/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .XML index 66c57820..79200bb6 100644 --- a/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .XML @@ -1,7 +1,7 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON index fde40646..448a84d6 100644 --- a/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON @@ -24,7 +24,6 @@ "transcodedSuffix": "mp3", "duration": 146, "bitRate": 320, - "isVideo": false, "bpm": 127, "comment": "a comment", "sortName": "sorted title", @@ -116,7 +115,6 @@ { "id": "", "isDir": false, - "isVideo": false, "bpm": 0, "comment": "", "sortName": "", diff --git a/server/subsonic/responses/.snapshots/Responses Child with data should match .XML b/server/subsonic/responses/.snapshots/Responses Child with data should match .XML index faea8ee9..2de1efbf 100644 --- a/server/subsonic/responses/.snapshots/Responses Child with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses Child with data should match .XML @@ -1,6 +1,6 @@ - + ISRC-1 ISRC-2 @@ -25,7 +25,7 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses Child without data should match .JSON b/server/subsonic/responses/.snapshots/Responses Child without data should match .JSON index 66b49830..2d099583 100644 --- a/server/subsonic/responses/.snapshots/Responses Child without data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses Child without data should match .JSON @@ -8,8 +8,7 @@ "child": [ { "id": "1", - "isDir": false, - "isVideo": false + "isDir": false } ], "id": "", diff --git a/server/subsonic/responses/.snapshots/Responses Child without data should match .XML b/server/subsonic/responses/.snapshots/Responses Child without data should match .XML index d43b9d3e..3e5a1cf1 100644 --- a/server/subsonic/responses/.snapshots/Responses Child without data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses Child without data should match .XML @@ -1,5 +1,5 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses Child without data should match OpenSubsonic .JSON b/server/subsonic/responses/.snapshots/Responses Child without data should match OpenSubsonic .JSON index 1af2ec4a..c3ccc6cd 100644 --- a/server/subsonic/responses/.snapshots/Responses Child without data should match OpenSubsonic .JSON +++ b/server/subsonic/responses/.snapshots/Responses Child without data should match OpenSubsonic .JSON @@ -9,7 +9,6 @@ { "id": "1", "isDir": false, - "isVideo": false, "bpm": 0, "comment": "", "sortName": "", diff --git a/server/subsonic/responses/.snapshots/Responses Child without data should match OpenSubsonic .XML b/server/subsonic/responses/.snapshots/Responses Child without data should match OpenSubsonic .XML index d43b9d3e..3e5a1cf1 100644 --- a/server/subsonic/responses/.snapshots/Responses Child without data should match OpenSubsonic .XML +++ b/server/subsonic/responses/.snapshots/Responses Child without data should match OpenSubsonic .XML @@ -1,5 +1,5 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses Directory with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Directory with data should match .JSON index daa7b9c7..c984c70d 100644 --- a/server/subsonic/responses/.snapshots/Responses Directory with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses Directory with data should match .JSON @@ -9,8 +9,7 @@ { "id": "1", "isDir": false, - "title": "title", - "isVideo": false + "title": "title" } ], "id": "1", diff --git a/server/subsonic/responses/.snapshots/Responses Directory with data should match .XML b/server/subsonic/responses/.snapshots/Responses Directory with data should match .XML index 2ac4f952..0b1191ba 100644 --- a/server/subsonic/responses/.snapshots/Responses Directory with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses Directory with data should match .XML @@ -1,5 +1,5 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .JSON b/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .JSON index eb771692..e5875873 100644 --- a/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .JSON @@ -9,8 +9,7 @@ { "id": "1", "isDir": false, - "title": "title", - "isVideo": false + "title": "title" } ], "current": "111", diff --git a/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .XML b/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .XML index 1156af0a..b7a054b8 100644 --- a/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .XML @@ -1,5 +1,5 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses PlayQueueByIndex with data should match .JSON b/server/subsonic/responses/.snapshots/Responses PlayQueueByIndex with data should match .JSON index efc032ca..3fa5b608 100644 --- a/server/subsonic/responses/.snapshots/Responses PlayQueueByIndex with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses PlayQueueByIndex with data should match .JSON @@ -9,8 +9,7 @@ { "id": "1", "isDir": false, - "title": "title", - "isVideo": false + "title": "title" } ], "currentIndex": 0, diff --git a/server/subsonic/responses/.snapshots/Responses PlayQueueByIndex with data should match .XML b/server/subsonic/responses/.snapshots/Responses PlayQueueByIndex with data should match .XML index 1d31b334..20f4994d 100644 --- a/server/subsonic/responses/.snapshots/Responses PlayQueueByIndex with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses PlayQueueByIndex with data should match .XML @@ -1,5 +1,5 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses Playlists with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Playlists with data should match .JSON index b6e996d6..5263fb07 100644 --- a/server/subsonic/responses/.snapshots/Responses Playlists with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses Playlists with data should match .JSON @@ -23,7 +23,6 @@ "name": "bbb", "songCount": 0, "duration": 0, - "public": false, "created": "0001-01-01T00:00:00Z", "changed": "0001-01-01T00:00:00Z" } diff --git a/server/subsonic/responses/.snapshots/Responses Playlists with data should match .XML b/server/subsonic/responses/.snapshots/Responses Playlists with data should match .XML index 100301af..6bc26c59 100644 --- a/server/subsonic/responses/.snapshots/Responses Playlists with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses Playlists with data should match .XML @@ -1,6 +1,6 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses Shares with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Shares with data should match .JSON index 0c08be37..cca38ba5 100644 --- a/server/subsonic/responses/.snapshots/Responses Shares with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses Shares with data should match .JSON @@ -14,8 +14,7 @@ "title": "title", "album": "album", "artist": "artist", - "duration": 120, - "isVideo": false + "duration": 120 }, { "id": "2", @@ -23,8 +22,7 @@ "title": "title 2", "album": "album", "artist": "artist", - "duration": 300, - "isVideo": false + "duration": 300 } ], "id": "ABC123", diff --git a/server/subsonic/responses/.snapshots/Responses Shares with data should match .XML b/server/subsonic/responses/.snapshots/Responses Shares with data should match .XML index 36cfc25f..ba63071b 100644 --- a/server/subsonic/responses/.snapshots/Responses Shares with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses Shares with data should match .XML @@ -1,8 +1,8 @@ - - + + diff --git a/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .JSON b/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .JSON index 7df08ded..ff30c1a2 100644 --- a/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .JSON @@ -9,8 +9,7 @@ { "id": "1", "isDir": false, - "title": "title", - "isVideo": false + "title": "title" } ] } diff --git a/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .XML b/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .XML index b05443a9..06f07a3b 100644 --- a/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .XML @@ -1,5 +1,5 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .JSON b/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .JSON index 73eda015..49331cf1 100644 --- a/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .JSON @@ -9,8 +9,7 @@ { "id": "1", "isDir": false, - "title": "title", - "isVideo": false + "title": "title" } ] } diff --git a/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .XML b/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .XML index 0402f031..4e80da12 100644 --- a/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .XML @@ -1,5 +1,5 @@ - + diff --git a/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .JSON b/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .JSON index 575c9b7f..1c871a43 100644 --- a/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .JSON @@ -9,8 +9,7 @@ { "id": "1", "isDir": false, - "title": "title", - "isVideo": false + "title": "title" } ] } diff --git a/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .XML b/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .XML index 35a77cb6..8991725b 100644 --- a/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .XML @@ -1,5 +1,5 @@ - + diff --git a/server/subsonic/responses/responses.go b/server/subsonic/responses/responses.go index 0724d2ff..de47c54e 100644 --- a/server/subsonic/responses/responses.go +++ b/server/subsonic/responses/responses.go @@ -161,7 +161,7 @@ type Child struct { Type string `xml:"type,attr,omitempty" json:"type,omitempty"` UserRating int32 `xml:"userRating,attr,omitempty" json:"userRating,omitempty"` SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"` - IsVideo bool `xml:"isVideo,attr" json:"isVideo"` + IsVideo bool `xml:"isVideo,attr,omitempty" json:"isVideo,omitempty"` BookmarkPosition int64 `xml:"bookmarkPosition,attr,omitempty" json:"bookmarkPosition,omitempty"` /* @@ -177,7 +177,7 @@ type OpenSubsonicChild struct { SortName string `xml:"sortName,attr,omitempty" json:"sortName"` MediaType MediaType `xml:"mediaType,attr,omitempty" json:"mediaType"` MusicBrainzId string `xml:"musicBrainzId,attr,omitempty" json:"musicBrainzId"` - Isrc Array[string] `xml:"isrc,omitempty" json:"isrc"` + Isrc Array[string] `xml:"isrc,omitempty" json:"isrc"` Genres Array[ItemGenre] `xml:"genres,omitempty" json:"genres"` ReplayGain ReplayGain `xml:"replayGain,omitempty" json:"replayGain"` ChannelCount int32 `xml:"channelCount,attr,omitempty" json:"channelCount"` @@ -308,7 +308,7 @@ type Playlist struct { Comment string `xml:"comment,attr,omitempty" json:"comment,omitempty"` SongCount int32 `xml:"songCount,attr" json:"songCount"` Duration int32 `xml:"duration,attr" json:"duration"` - Public bool `xml:"public,attr" json:"public"` + Public bool `xml:"public,attr,omitempty" json:"public,omitempty"` Owner string `xml:"owner,attr,omitempty" json:"owner,omitempty"` Created time.Time `xml:"created,attr" json:"created"` Changed time.Time `xml:"changed,attr" json:"changed"`