mirror of
https://github.com/navidrome/navidrome.git
synced 2026-06-19 07:37:15 +00:00
fix(subsonic): mark AlbumID3 songCount and created as required
The Subsonic API spec defines songCount and created as required attributes on AlbumID3, but they were tagged with omitempty in our response struct, allowing them to be silently dropped from responses (e.g. when songCount was 0). Created was also a *time.Time, which compounded the omitempty behavior. Remove omitempty from both fields and change Created from *time.Time to time.Time so they are always serialized, matching the spec contract that clients rely on. The buildAlbumID3 helper and its tests are updated for the non-pointer Created, and the AlbumWithSongsID3 snapshots are regenerated to include the now-always-present fields.
This commit is contained in:
@@ -441,7 +441,7 @@ func buildAlbumID3(ctx context.Context, album model.Album) responses.AlbumID3 {
|
||||
dir.PlayCount = album.PlayCount
|
||||
dir.Year = int32(cmp.Or(album.MaxOriginalYear, album.MaxYear))
|
||||
dir.Genre = album.Genre
|
||||
dir.Created = new(albumCreatedAt(album))
|
||||
dir.Created = albumCreatedAt(album)
|
||||
if album.Starred {
|
||||
dir.Starred = album.StarredAt
|
||||
}
|
||||
|
||||
@@ -576,30 +576,27 @@ var _ = Describe("helpers", func() {
|
||||
t := time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC)
|
||||
al := model.Album{ID: "a1", Name: "A", CreatedAt: t}
|
||||
dir := buildAlbumID3(ctx, al)
|
||||
Expect(dir.Created).ToNot(BeNil())
|
||||
Expect(*dir.Created).To(Equal(t))
|
||||
Expect(dir.Created).To(Equal(t))
|
||||
})
|
||||
|
||||
It("falls back to UpdatedAt when CreatedAt is zero", func() {
|
||||
updated := time.Date(2019, 5, 6, 7, 8, 9, 0, time.UTC)
|
||||
al := model.Album{ID: "a2", Name: "A", UpdatedAt: updated}
|
||||
dir := buildAlbumID3(ctx, al)
|
||||
Expect(dir.Created).ToNot(BeNil())
|
||||
Expect(*dir.Created).To(Equal(updated))
|
||||
Expect(dir.Created).To(Equal(updated))
|
||||
})
|
||||
|
||||
It("falls back to ImportedAt when CreatedAt and UpdatedAt are zero", func() {
|
||||
imported := time.Date(2021, 8, 9, 10, 11, 12, 0, time.UTC)
|
||||
al := model.Album{ID: "a3", Name: "A", ImportedAt: imported}
|
||||
dir := buildAlbumID3(ctx, al)
|
||||
Expect(dir.Created).ToNot(BeNil())
|
||||
Expect(*dir.Created).To(Equal(imported))
|
||||
Expect(dir.Created).To(Equal(imported))
|
||||
})
|
||||
|
||||
It("never leaves Created nil even when all timestamps are zero", func() {
|
||||
It("leaves Created as zero time when all timestamps are zero", func() {
|
||||
al := model.Album{ID: "a4", Name: "A"}
|
||||
dir := buildAlbumID3(ctx, al)
|
||||
Expect(dir.Created).ToNot(BeNil())
|
||||
Expect(dir.Created.IsZero()).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
+2
@@ -8,7 +8,9 @@
|
||||
"id": "1",
|
||||
"name": "album",
|
||||
"artist": "artist",
|
||||
"songCount": 0,
|
||||
"duration": 292,
|
||||
"created": "0001-01-01T00:00:00Z",
|
||||
"genre": "rock",
|
||||
"userRating": 4,
|
||||
"genres": [
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.16.1" type="navidrome" serverVersion="v0.55.0" openSubsonic="true">
|
||||
<album id="1" name="album" artist="artist" duration="292" genre="rock" userRating="4" musicBrainzId="1234" isCompilation="true" sortName="sorted album" displayArtist="artist1 & artist2" explicitStatus="clean" version="Deluxe Edition">
|
||||
<album id="1" name="album" artist="artist" songCount="0" duration="292" created="0001-01-01T00:00:00Z" genre="rock" userRating="4" musicBrainzId="1234" isCompilation="true" sortName="sorted album" displayArtist="artist1 & artist2" explicitStatus="clean" version="Deluxe Edition">
|
||||
<genres name="rock"></genres>
|
||||
<genres name="progressive"></genres>
|
||||
<discTitles disc="1" title="disc 1"></discTitles>
|
||||
|
||||
+3
-1
@@ -7,6 +7,8 @@
|
||||
"album": {
|
||||
"id": "",
|
||||
"name": "",
|
||||
"duration": 0
|
||||
"songCount": 0,
|
||||
"duration": 0,
|
||||
"created": "0001-01-01T00:00:00Z"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.16.1" type="navidrome" serverVersion="v0.55.0" openSubsonic="true">
|
||||
<album id="" name="" duration="0"></album>
|
||||
<album id="" name="" songCount="0" duration="0" created="0001-01-01T00:00:00Z"></album>
|
||||
</subsonic-response>
|
||||
|
||||
+2
@@ -7,7 +7,9 @@
|
||||
"album": {
|
||||
"id": "",
|
||||
"name": "",
|
||||
"songCount": 0,
|
||||
"duration": 0,
|
||||
"created": "0001-01-01T00:00:00Z",
|
||||
"userRating": 0,
|
||||
"genres": [],
|
||||
"musicBrainzId": "",
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.16.1" type="navidrome" serverVersion="v0.55.0" openSubsonic="true">
|
||||
<album id="" name="" duration="0"></album>
|
||||
<album id="" name="" songCount="0" duration="0" created="0001-01-01T00:00:00Z"></album>
|
||||
</subsonic-response>
|
||||
|
||||
@@ -251,10 +251,10 @@ type AlbumID3 struct {
|
||||
Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"`
|
||||
ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"`
|
||||
CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
|
||||
SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"`
|
||||
SongCount int32 `xml:"songCount,attr" json:"songCount"`
|
||||
Duration int32 `xml:"duration,attr" json:"duration"`
|
||||
PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"`
|
||||
Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"`
|
||||
Created time.Time `xml:"created,attr" json:"created"`
|
||||
Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
|
||||
Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
|
||||
Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"`
|
||||
|
||||
Reference in New Issue
Block a user