mirror of
https://github.com/navidrome/navidrome.git
synced 2026-06-19 07:37:15 +00:00
refactor: multiple syntax updates for Go 1.26
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
+2
-1
@@ -37,5 +37,6 @@ AGENTS.md
|
||||
*.wasm
|
||||
*.ndp
|
||||
openspec/
|
||||
.agents
|
||||
go.work*
|
||||
.worktrees/
|
||||
.worktrees/
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/djherbis/times"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/metadata"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -91,8 +90,7 @@ var _ = Describe("Extractor", func() {
|
||||
info.FileInfo = testFileInfo{FileInfo: fileInfo}
|
||||
|
||||
metadata := metadata.New(path, info)
|
||||
mf := metadata.ToMediaFile(1, "folderID")
|
||||
return &mf
|
||||
return new(metadata.ToMediaFile(1, "folderID"))
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
@@ -109,7 +107,7 @@ var _ = Describe("Extractor", func() {
|
||||
Expect(mf.RGAlbumPeak).To(Equal(albumPeak))
|
||||
},
|
||||
Entry("mp3 with no replaygain", "no_replaygain.mp3", nil, nil, nil, nil),
|
||||
Entry("mp3 with no zero replaygain", "zero_replaygain.mp3", gg.P(0.0), gg.P(1.0), gg.P(0.0), gg.P(1.0)),
|
||||
Entry("mp3 with no zero replaygain", "zero_replaygain.mp3", new(0.0), new(1.0), new(0.0), new(1.0)),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -120,8 +118,8 @@ var _ = Describe("Extractor", func() {
|
||||
DisplayTitle: "",
|
||||
Lang: code,
|
||||
Line: []model.Line{
|
||||
{Start: gg.P(int64(0)), Value: "This is"},
|
||||
{Start: gg.P(int64(2500)), Value: secondLine},
|
||||
{Start: new(int64(0)), Value: "This is"},
|
||||
{Start: new(int64(2500)), Value: secondLine},
|
||||
},
|
||||
Offset: nil,
|
||||
Synced: true,
|
||||
|
||||
Vendored
+2
-2
@@ -153,7 +153,7 @@ func (e *provider) populateAlbumInfo(ctx context.Context, album auxAlbum) (auxAl
|
||||
return album, err
|
||||
}
|
||||
|
||||
album.ExternalInfoUpdatedAt = P(time.Now())
|
||||
album.ExternalInfoUpdatedAt = new(time.Now())
|
||||
album.ExternalUrl = info.URL
|
||||
|
||||
if info.Description != "" {
|
||||
@@ -269,7 +269,7 @@ func (e *provider) populateArtistInfo(ctx context.Context, artist auxArtist) (au
|
||||
return artist, ctx.Err()
|
||||
}
|
||||
|
||||
artist.ExternalInfoUpdatedAt = P(time.Now())
|
||||
artist.ExternalInfoUpdatedAt = new(time.Now())
|
||||
err := e.ds.Artist(ctx).UpdateExternalInfo(&artist.Artist)
|
||||
if err != nil {
|
||||
log.Error(ctx, "Error trying to update artist external information", "id", artist.ID, "name", artistName,
|
||||
|
||||
+2
-4
@@ -272,12 +272,11 @@ var _ = Describe("Provider - ArtistImage", func() {
|
||||
|
||||
It("returns cached URL and does not call agent when info is not expired", func() {
|
||||
// Arrange: artist has a cached image URL with recent ExternalInfoUpdatedAt
|
||||
recentTime := time.Now().Add(-1 * time.Minute)
|
||||
cachedArtist := &model.Artist{
|
||||
ID: "artist-cached",
|
||||
Name: "Cached Artist",
|
||||
LargeImageUrl: "http://example.com/cached-large.jpg",
|
||||
ExternalInfoUpdatedAt: &recentTime,
|
||||
ExternalInfoUpdatedAt: new(time.Now().Add(-1 * time.Minute)),
|
||||
}
|
||||
mockArtistRepo.On("Get", "artist-cached").Return(cachedArtist, nil).Maybe()
|
||||
expectedURL, _ := url.Parse("http://example.com/cached-large.jpg")
|
||||
@@ -304,12 +303,11 @@ var _ = Describe("Provider - ArtistImage", func() {
|
||||
It("returns stale URL and enqueues refresh when info is expired", func() {
|
||||
// Arrange
|
||||
conf.Server.DevArtistInfoTimeToLive = 1 * time.Nanosecond
|
||||
expiredTime := time.Now().Add(-1 * time.Hour)
|
||||
staleArtist := &model.Artist{
|
||||
ID: "artist-expired",
|
||||
Name: "Expired Artist",
|
||||
LargeImageUrl: "http://example.com/expired-large.jpg",
|
||||
ExternalInfoUpdatedAt: &expiredTime,
|
||||
ExternalInfoUpdatedAt: new(time.Now().Add(-1 * time.Hour)),
|
||||
}
|
||||
mockArtistRepo.On("Get", "artist-expired").Return(staleArtist, nil).Maybe()
|
||||
expectedURL, _ := url.Parse("http://example.com/expired-large.jpg")
|
||||
|
||||
+2
-3
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/stretchr/testify/mock"
|
||||
@@ -90,7 +89,7 @@ var _ = Describe("Provider - UpdateAlbumInfo", func() {
|
||||
ExternalUrl: "http://cached.com/album",
|
||||
Description: "Cached Desc",
|
||||
LargeImageUrl: "http://cached.com/large.jpg",
|
||||
ExternalInfoUpdatedAt: gg.P(now.Add(-conf.Server.DevAlbumInfoTimeToLive / 2)),
|
||||
ExternalInfoUpdatedAt: new(now.Add(-conf.Server.DevAlbumInfoTimeToLive / 2)),
|
||||
}
|
||||
mockAlbumRepo.SetData(model.Albums{*originalAlbum})
|
||||
|
||||
@@ -113,7 +112,7 @@ var _ = Describe("Provider - UpdateAlbumInfo", func() {
|
||||
ExternalUrl: "http://expired.com/album",
|
||||
Description: "Expired Desc",
|
||||
LargeImageUrl: "http://expired.com/large.jpg",
|
||||
ExternalInfoUpdatedAt: gg.P(expiredTime),
|
||||
ExternalInfoUpdatedAt: new(expiredTime),
|
||||
}
|
||||
mockAlbumRepo.SetData(model.Albums{*originalAlbum})
|
||||
|
||||
|
||||
+3
-4
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/stretchr/testify/mock"
|
||||
@@ -137,7 +136,7 @@ var _ = Describe("Provider - UpdateArtistInfo", func() {
|
||||
ExternalUrl: "http://cached.url",
|
||||
Biography: "Cached Bio",
|
||||
LargeImageUrl: "http://cached_large.jpg",
|
||||
ExternalInfoUpdatedAt: gg.P(now.Add(-conf.Server.DevArtistInfoTimeToLive / 2)),
|
||||
ExternalInfoUpdatedAt: new(now.Add(-conf.Server.DevArtistInfoTimeToLive / 2)),
|
||||
SimilarArtists: model.Artists{
|
||||
{ID: "ar-similar-present", Name: "Similar Present"},
|
||||
{ID: "ar-similar-absent", Name: "Similar Absent"},
|
||||
@@ -174,7 +173,7 @@ var _ = Describe("Provider - UpdateArtistInfo", func() {
|
||||
originalArtist := &model.Artist{
|
||||
ID: "ar-expired",
|
||||
Name: "Expired Artist",
|
||||
ExternalInfoUpdatedAt: gg.P(expiredTime),
|
||||
ExternalInfoUpdatedAt: new(expiredTime),
|
||||
SimilarArtists: model.Artists{
|
||||
{ID: "ar-exp-similar", Name: "Expired Similar"},
|
||||
},
|
||||
@@ -205,7 +204,7 @@ var _ = Describe("Provider - UpdateArtistInfo", func() {
|
||||
originalArtist := &model.Artist{
|
||||
ID: "ar-similar-test",
|
||||
Name: "Similar Test Artist",
|
||||
ExternalInfoUpdatedAt: gg.P(now.Add(-conf.Server.DevArtistInfoTimeToLive / 2)),
|
||||
ExternalInfoUpdatedAt: new(now.Add(-conf.Server.DevArtistInfoTimeToLive / 2)),
|
||||
SimilarArtists: model.Artists{
|
||||
{ID: "ar-sim-present", Name: "Similar Present"},
|
||||
{ID: "", Name: "Similar Absent Raw"},
|
||||
|
||||
@@ -326,8 +326,7 @@ func (j *ffCmd) start(ctx context.Context) error {
|
||||
|
||||
func (j *ffCmd) wait() {
|
||||
if err := j.cmd.Wait(); err != nil {
|
||||
var exitErr *exec.ExitError
|
||||
if errors.As(err, &exitErr) {
|
||||
if exitErr, ok := errors.AsType[*exec.ExitError](err); ok {
|
||||
errMsg := fmt.Sprintf("%s exited with non-zero status code: %d", j.args[0], exitErr.ExitCode())
|
||||
if stderrOutput := strings.TrimSpace(j.stderr.String()); stderrOutput != "" {
|
||||
errMsg += ": " + stderrOutput
|
||||
|
||||
+1
-2
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/metadata"
|
||||
. "github.com/navidrome/navidrome/utils/gg"
|
||||
)
|
||||
|
||||
type InspectOutput struct {
|
||||
@@ -44,7 +43,7 @@ func Inspect(filePath string, libraryId int, folderId string) (*InspectOutput, e
|
||||
result := &InspectOutput{
|
||||
File: filePath,
|
||||
RawTags: tags[file].Tags,
|
||||
MappedTags: P(md.ToMediaFile(libraryId, folderId)),
|
||||
MappedTags: new(md.ToMediaFile(libraryId, folderId)),
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
"github.com/navidrome/navidrome/utils"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -32,15 +31,15 @@ var _ = Describe("sources", func() {
|
||||
Lang: "eng",
|
||||
Line: []model.Line{
|
||||
{
|
||||
Start: gg.P(int64(18800)),
|
||||
Start: new(int64(18800)),
|
||||
Value: "We're no strangers to love",
|
||||
},
|
||||
{
|
||||
Start: gg.P(int64(22801)),
|
||||
Start: new(int64(22801)),
|
||||
Value: "You know the rules and so do I",
|
||||
},
|
||||
},
|
||||
Offset: gg.P(int64(-100)),
|
||||
Offset: new(int64(-100)),
|
||||
Synced: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -74,15 +73,15 @@ var _ = Describe("sources", func() {
|
||||
Lang: "eng",
|
||||
Line: []model.Line{
|
||||
{
|
||||
Start: gg.P(int64(18800)),
|
||||
Start: new(int64(18800)),
|
||||
Value: "We're no strangers to love",
|
||||
},
|
||||
{
|
||||
Start: gg.P(int64(22801)),
|
||||
Start: new(int64(22801)),
|
||||
Value: "You know the rules and so do I",
|
||||
},
|
||||
},
|
||||
Offset: gg.P(int64(-100)),
|
||||
Offset: new(int64(-100)),
|
||||
Synced: true,
|
||||
},
|
||||
}))
|
||||
@@ -122,7 +121,7 @@ var _ = Describe("sources", func() {
|
||||
// The critical assertion: even with BOM, synced should be true
|
||||
Expect(lyrics[0].Synced).To(BeTrue(), "Lyrics with BOM marker should be recognized as synced")
|
||||
Expect(lyrics[0].Line).To(HaveLen(1))
|
||||
Expect(lyrics[0].Line[0].Start).To(Equal(gg.P(int64(0))))
|
||||
Expect(lyrics[0].Line[0].Start).To(Equal(new(int64(0))))
|
||||
Expect(lyrics[0].Line[0].Value).To(ContainSubstring("作曲"))
|
||||
})
|
||||
|
||||
@@ -137,9 +136,9 @@ var _ = Describe("sources", func() {
|
||||
// UTF-16 should be properly converted to UTF-8
|
||||
Expect(lyrics[0].Synced).To(BeTrue(), "UTF-16 encoded lyrics should be recognized as synced")
|
||||
Expect(lyrics[0].Line).To(HaveLen(2))
|
||||
Expect(lyrics[0].Line[0].Start).To(Equal(gg.P(int64(18800))))
|
||||
Expect(lyrics[0].Line[0].Start).To(Equal(new(int64(18800))))
|
||||
Expect(lyrics[0].Line[0].Value).To(Equal("We're no strangers to love"))
|
||||
Expect(lyrics[0].Line[1].Start).To(Equal(gg.P(int64(22801))))
|
||||
Expect(lyrics[0].Line[1].Start).To(Equal(new(int64(22801))))
|
||||
Expect(lyrics[0].Line[1].Value).To(Equal("You know the rules and so do I"))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -62,8 +62,7 @@ func (j *Executor) start(ctx context.Context) error {
|
||||
|
||||
func (j *Executor) wait() {
|
||||
if err := j.cmd.Wait(); err != nil {
|
||||
var exitErr *exec.ExitError
|
||||
if errors.As(err, &exitErr) {
|
||||
if exitErr, ok := errors.AsType[*exec.ExitError](err); ok {
|
||||
_ = j.out.CloseWithError(fmt.Errorf("%s exited with non-zero status code: %d", j.args[0], exitErr.ExitCode()))
|
||||
} else {
|
||||
_ = j.out.CloseWithError(fmt.Errorf("waiting %s cmd: %w", j.args[0], err))
|
||||
|
||||
@@ -59,8 +59,7 @@ func (s *playlists) parseNSP(_ context.Context, pls *model.Playlist, reader io.R
|
||||
}
|
||||
err = json.Unmarshal(input, nsp)
|
||||
if err != nil {
|
||||
var syntaxErr *json.SyntaxError
|
||||
if errors.As(err, &syntaxErr) {
|
||||
if syntaxErr, ok := errors.AsType[*json.SyntaxError](err); ok {
|
||||
line, col := getPositionFromOffset(input, syntaxErr.Offset)
|
||||
return fmt.Errorf("JSON syntax error in SmartPlaylist at line %d, column %d: %w", line, col, err)
|
||||
}
|
||||
|
||||
@@ -144,29 +144,25 @@ var _ = Describe("Playlists", func() {
|
||||
|
||||
It("allows owner to update their playlist", func() {
|
||||
ctx = request.WithUser(ctx, model.User{ID: "user-1", IsAdmin: false})
|
||||
newName := "Updated Name"
|
||||
err := ps.Update(ctx, "pls-1", &newName, nil, nil, nil, nil)
|
||||
err := ps.Update(ctx, "pls-1", new("Updated Name"), nil, nil, nil, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("allows admin to update any playlist", func() {
|
||||
ctx = request.WithUser(ctx, model.User{ID: "admin-1", IsAdmin: true})
|
||||
newName := "Updated Name"
|
||||
err := ps.Update(ctx, "pls-other", &newName, nil, nil, nil, nil)
|
||||
err := ps.Update(ctx, "pls-other", new("Updated Name"), nil, nil, nil, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("denies non-owner, non-admin from updating", func() {
|
||||
ctx = request.WithUser(ctx, model.User{ID: "other-user", IsAdmin: false})
|
||||
newName := "Updated Name"
|
||||
err := ps.Update(ctx, "pls-1", &newName, nil, nil, nil, nil)
|
||||
err := ps.Update(ctx, "pls-1", new("Updated Name"), nil, nil, nil, nil)
|
||||
Expect(err).To(MatchError(model.ErrNotAuthorized))
|
||||
})
|
||||
|
||||
It("returns error when playlist not found", func() {
|
||||
ctx = request.WithUser(ctx, model.User{ID: "user-1", IsAdmin: false})
|
||||
newName := "Updated Name"
|
||||
err := ps.Update(ctx, "nonexistent", &newName, nil, nil, nil, nil)
|
||||
err := ps.Update(ctx, "nonexistent", new("Updated Name"), nil, nil, nil, nil)
|
||||
Expect(err).To(Equal(model.ErrNotFound))
|
||||
})
|
||||
|
||||
@@ -184,8 +180,7 @@ var _ = Describe("Playlists", func() {
|
||||
|
||||
It("allows metadata updates on a smart playlist", func() {
|
||||
ctx = request.WithUser(ctx, model.User{ID: "user-1", IsAdmin: false})
|
||||
newName := "Updated Smart"
|
||||
err := ps.Update(ctx, "pls-smart", &newName, nil, nil, nil, nil)
|
||||
err := ps.Update(ctx, "pls-smart", new("Updated Smart"), nil, nil, nil, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -63,7 +63,6 @@ var _ = Describe("REST Adapter", func() {
|
||||
It("clears server-managed fields to prevent injection via REST API", func() {
|
||||
ctx = request.WithUser(ctx, model.User{ID: "user-1", IsAdmin: false})
|
||||
repo = ps.NewRepository(ctx).(rest.Persistable)
|
||||
now := time.Now()
|
||||
pls := &model.Playlist{
|
||||
Name: "Legit Playlist",
|
||||
Comment: "A comment",
|
||||
@@ -73,7 +72,7 @@ var _ = Describe("REST Adapter", func() {
|
||||
Sync: true,
|
||||
UploadedImage: "injected-image-path",
|
||||
ExternalImageURL: "http://evil.example.com/ssrf",
|
||||
EvaluatedAt: &now,
|
||||
EvaluatedAt: new(time.Now()),
|
||||
}
|
||||
_, err := repo.Save(pls)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
@@ -1133,8 +1133,7 @@ func (f *fakeScrobbler) PlaybackReport(ctx context.Context, info PlaybackSession
|
||||
if f.Error != nil {
|
||||
return f.Error
|
||||
}
|
||||
uid := info.UserId
|
||||
f.userID.Store(&uid)
|
||||
f.userID.Store(new(info.UserId))
|
||||
f.LastPlaybackReport.Store(&info)
|
||||
return nil
|
||||
}
|
||||
|
||||
+2
-2
@@ -41,7 +41,7 @@ func (s *shareService) Load(ctx context.Context, id string) (*model.Share, error
|
||||
if !expiresAt.IsZero() && expiresAt.Before(time.Now()) {
|
||||
return nil, model.ErrExpired
|
||||
}
|
||||
share.LastVisitedAt = P(time.Now())
|
||||
share.LastVisitedAt = new(time.Now())
|
||||
share.VisitCount++
|
||||
|
||||
err = repo.(rest.Persistable).Update(id, share, "last_visited_at", "visit_count")
|
||||
@@ -95,7 +95,7 @@ func (r *shareRepositoryWrapper) Save(entity any) (string, error) {
|
||||
}
|
||||
s.ID = id
|
||||
if V(s.ExpiresAt).IsZero() {
|
||||
s.ExpiresAt = P(time.Now().Add(conf.Server.DefaultShareExpiration))
|
||||
s.ExpiresAt = new(time.Now().Add(conf.Server.DefaultShareExpiration))
|
||||
}
|
||||
|
||||
firstId := strings.SplitN(s.ResourceIDs, ",", 2)[0]
|
||||
|
||||
@@ -11,8 +11,7 @@ import (
|
||||
var _ = Describe("ArtworkID", func() {
|
||||
Describe("NewArtworkID()", func() {
|
||||
It("creates a valid parseable ArtworkID", func() {
|
||||
now := time.Now()
|
||||
id := model.NewArtworkID(model.KindAlbumArtwork, "1234", &now)
|
||||
id := model.NewArtworkID(model.KindAlbumArtwork, "1234", new(time.Now()))
|
||||
parsedId, err := model.ParseArtworkID(id.String())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(parsedId.Kind).To(Equal(id.Kind))
|
||||
|
||||
+22
-30
@@ -8,14 +8,13 @@ import (
|
||||
|
||||
var _ = Describe("ToLyrics", func() {
|
||||
It("should parse tags with spaces", func() {
|
||||
num := int64(1551)
|
||||
lyrics, err := ToLyrics("xxx", "[lang: eng ]\n[offset: 1551 ]\n[ti: A title ]\n[ar: An artist ]\n[00:00.00]Hi there")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lyrics.Lang).To(Equal("eng"))
|
||||
Expect(lyrics.Synced).To(BeTrue())
|
||||
Expect(lyrics.DisplayArtist).To(Equal("An artist"))
|
||||
Expect(lyrics.DisplayTitle).To(Equal("A title"))
|
||||
Expect(lyrics.Offset).To(Equal(&num))
|
||||
Expect(lyrics.Offset).To(Equal(new(int64(1551))))
|
||||
})
|
||||
|
||||
It("Should ignore bad offset", func() {
|
||||
@@ -25,39 +24,36 @@ var _ = Describe("ToLyrics", func() {
|
||||
})
|
||||
|
||||
It("should accept lines with no text and weird times", func() {
|
||||
a, b, c, d := int64(0), int64(10040), int64(40000), int64(1000*60*60)
|
||||
lyrics, err := ToLyrics("xxx", "[00:00.00]Hi there\n\n\n[00:10.040]\n[00:40]Test\n[01:00:00]late")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lyrics.Synced).To(BeTrue())
|
||||
Expect(lyrics.Line).To(Equal([]Line{
|
||||
{Start: &a, Value: "Hi there"},
|
||||
{Start: &b, Value: ""},
|
||||
{Start: &c, Value: "Test"},
|
||||
{Start: &d, Value: "late"},
|
||||
{Start: new(int64(0)), Value: "Hi there"},
|
||||
{Start: new(int64(10040)), Value: ""},
|
||||
{Start: new(int64(40000)), Value: "Test"},
|
||||
{Start: new(int64(1000 * 60 * 60)), Value: "late"},
|
||||
}))
|
||||
})
|
||||
|
||||
It("Should support multiple timestamps per line", func() {
|
||||
a, b, c, d := int64(0), int64(10000), int64(13*60*1000), int64(1000*60*60*51)
|
||||
lyrics, err := ToLyrics("xxx", "[00:00.00] [00:10.00]Repeated\n[13:00][51:00:00.00]")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lyrics.Synced).To(BeTrue())
|
||||
Expect(lyrics.Line).To(Equal([]Line{
|
||||
{Start: &a, Value: "Repeated"},
|
||||
{Start: &b, Value: "Repeated"},
|
||||
{Start: &c, Value: ""},
|
||||
{Start: &d, Value: ""},
|
||||
{Start: new(int64(0)), Value: "Repeated"},
|
||||
{Start: new(int64(10000)), Value: "Repeated"},
|
||||
{Start: new(int64(13 * 60 * 1000)), Value: ""},
|
||||
{Start: new(int64(1000 * 60 * 60 * 51)), Value: ""},
|
||||
}))
|
||||
})
|
||||
|
||||
It("Should support parsing multiline string", func() {
|
||||
a, b := int64(0), int64(10*60*1000+1)
|
||||
lyrics, err := ToLyrics("xxx", "[00:00.00]This is\na multiline \n\n [:0] string\n[10:00.001]This is\nalso one")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lyrics.Synced).To(BeTrue())
|
||||
Expect(lyrics.Line).To(Equal([]Line{
|
||||
{Start: &a, Value: "This is\na multiline\n\n[:0] string"},
|
||||
{Start: &b, Value: "This is\nalso one"},
|
||||
{Start: new(int64(0)), Value: "This is\na multiline\n\n[:0] string"},
|
||||
{Start: new(int64(10*60*1000 + 1)), Value: "This is\nalso one"},
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -71,49 +67,45 @@ var _ = Describe("ToLyrics", func() {
|
||||
})
|
||||
|
||||
It("Allows timestamp in middle of line if also at beginning", func() {
|
||||
a, b := int64(0), int64(1000)
|
||||
lyrics, err := ToLyrics("xxx", " [00:00] This is [00:00:00] be a synced file\n [00:01]Line 2")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lyrics.Synced).To(BeTrue())
|
||||
Expect(lyrics.Line).To(Equal([]Line{
|
||||
{Start: &a, Value: "This is [00:00:00] be a synced file"},
|
||||
{Start: &b, Value: "Line 2"},
|
||||
{Start: new(int64(0)), Value: "This is [00:00:00] be a synced file"},
|
||||
{Start: new(int64(1000)), Value: "Line 2"},
|
||||
}))
|
||||
})
|
||||
|
||||
It("Ignores lines in synchronized lyric prior to first timestamp", func() {
|
||||
a := int64(0)
|
||||
lyrics, err := ToLyrics("xxx", "This is some prelude\nThat doesn't\nmatter\n[00:00]Text")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lyrics.Synced).To(BeTrue())
|
||||
Expect(lyrics.Line).To(Equal([]Line{
|
||||
{Start: &a, Value: "Text"},
|
||||
{Start: new(int64(0)), Value: "Text"},
|
||||
}))
|
||||
})
|
||||
|
||||
It("Handles all possible ms cases", func() {
|
||||
a, b, c := int64(1), int64(10), int64(100)
|
||||
lyrics, err := ToLyrics("xxx", "[00:00.001]a\n[00:00.01]b\n[00:00.1]c")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lyrics.Synced).To(BeTrue())
|
||||
Expect(lyrics.Line).To(Equal([]Line{
|
||||
{Start: &a, Value: "a"},
|
||||
{Start: &b, Value: "b"},
|
||||
{Start: &c, Value: "c"},
|
||||
{Start: new(int64(1)), Value: "a"},
|
||||
{Start: new(int64(10)), Value: "b"},
|
||||
{Start: new(int64(100)), Value: "c"},
|
||||
}))
|
||||
})
|
||||
|
||||
It("Properly sorts repeated lyrics out of order", func() {
|
||||
a, b, c, d, e := int64(0), int64(10000), int64(40000), int64(13*60*1000), int64(1000*60*60*51)
|
||||
lyrics, err := ToLyrics("xxx", "[00:00.00] [13:00]Repeated\n[00:10.00][51:00:00.00]Test\n[00:40.00]Not repeated")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lyrics.Synced).To(BeTrue())
|
||||
Expect(lyrics.Line).To(Equal([]Line{
|
||||
{Start: &a, Value: "Repeated"},
|
||||
{Start: &b, Value: "Test"},
|
||||
{Start: &c, Value: "Not repeated"},
|
||||
{Start: &d, Value: "Repeated"},
|
||||
{Start: &e, Value: "Test"},
|
||||
{Start: new(int64(0)), Value: "Repeated"},
|
||||
{Start: new(int64(10000)), Value: "Test"},
|
||||
{Start: new(int64(40000)), Value: "Not repeated"},
|
||||
{Start: new(int64(13 * 60 * 1000)), Value: "Repeated"},
|
||||
{Start: new(int64(1000 * 60 * 60 * 51)), Value: "Test"},
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/metadata"
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
. "github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -108,8 +107,8 @@ var _ = Describe("ToMediaFile", func() {
|
||||
|
||||
expected := model.LyricList{
|
||||
{Lang: "eng", Line: []model.Line{
|
||||
{Value: "This is", Start: P(int64(0))},
|
||||
{Value: "English SYLT", Start: P(int64(2500))},
|
||||
{Value: "This is", Start: new(int64(0))},
|
||||
{Value: "English SYLT", Start: new(int64(2500))},
|
||||
}, Synced: true},
|
||||
{Lang: "xxx", Line: []model.Line{{Value: "Lyrics"}}, Synced: false},
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/metadata"
|
||||
"github.com/navidrome/navidrome/utils"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -274,8 +273,8 @@ var _ = Describe("Metadata", func() {
|
||||
mf := createMF("replaygain_track_gain", tagValue)
|
||||
Expect(mf.RGTrackGain).To(Equal(expected))
|
||||
},
|
||||
Entry("0", "0", gg.P(0.0)),
|
||||
Entry("1.2dB", "1.2dB", gg.P(1.2)),
|
||||
Entry("0", "0", new(0.0)),
|
||||
Entry("1.2dB", "1.2dB", new(1.2)),
|
||||
Entry("Infinity", "Infinity", nil),
|
||||
Entry("Invalid value", "INVALID VALUE", nil),
|
||||
Entry("NaN", "NaN", nil),
|
||||
@@ -285,9 +284,9 @@ var _ = Describe("Metadata", func() {
|
||||
mf := createMF("replaygain_track_peak", tagValue)
|
||||
Expect(mf.RGTrackPeak).To(Equal(expected))
|
||||
},
|
||||
Entry("0", "0", gg.P(0.0)),
|
||||
Entry("1.0", "1.0", gg.P(1.0)),
|
||||
Entry("0.5", "0.5", gg.P(0.5)),
|
||||
Entry("0", "0", new(0.0)),
|
||||
Entry("1.0", "1.0", new(1.0)),
|
||||
Entry("0.5", "0.5", new(0.5)),
|
||||
Entry("Invalid dB suffix", "0.7dB", nil),
|
||||
Entry("Infinity", "Infinity", nil),
|
||||
Entry("Invalid value", "INVALID VALUE", nil),
|
||||
@@ -299,8 +298,8 @@ var _ = Describe("Metadata", func() {
|
||||
Expect(mf.RGTrackGain).To(Equal(expected))
|
||||
|
||||
},
|
||||
Entry("0", "0", gg.P(5.0)),
|
||||
Entry("-3776", "-3776", gg.P(-9.75)),
|
||||
Entry("0", "0", new(5.0)),
|
||||
Entry("-3776", "-3776", new(-9.75)),
|
||||
Entry("Infinity", "Infinity", nil),
|
||||
Entry("Invalid value", "INVALID VALUE", nil),
|
||||
)
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/utils"
|
||||
. "github.com/navidrome/navidrome/utils/gg"
|
||||
"github.com/navidrome/navidrome/utils/slice"
|
||||
"github.com/pocketbase/dbx"
|
||||
)
|
||||
@@ -219,7 +218,7 @@ func (r *artistRepository) Exists(id string) (bool, error) {
|
||||
|
||||
func (r *artistRepository) Put(a *model.Artist, colsToUpdate ...string) error {
|
||||
dba := &dbArtist{Artist: a}
|
||||
dba.CreatedAt = P(time.Now())
|
||||
dba.CreatedAt = new(time.Now())
|
||||
dba.UpdatedAt = dba.CreatedAt
|
||||
_, err := r.put(dba.ID, dba, colsToUpdate...)
|
||||
return err
|
||||
|
||||
@@ -14,9 +14,8 @@ type genreRepository struct {
|
||||
}
|
||||
|
||||
func NewGenreRepository(ctx context.Context, db dbx.Builder) model.GenreRepository {
|
||||
genreFilter := model.TagGenre
|
||||
return &genreRepository{
|
||||
baseTagRepository: newBaseTagRepository(ctx, db, &genreFilter),
|
||||
baseTagRepository: newBaseTagRepository(ctx, db, new(model.TagGenre)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/request"
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/pocketbase/dbx"
|
||||
@@ -103,7 +102,7 @@ var (
|
||||
songAntenna = mf(model.MediaFile{ID: "1004", Title: "Antenna", ArtistID: "2", Artist: "Kraftwerk",
|
||||
AlbumID: "103",
|
||||
Path: p("kraft/radio/antenna.mp3"),
|
||||
RGAlbumGain: gg.P(1.0), RGAlbumPeak: gg.P(2.0), RGTrackGain: gg.P(3.0), RGTrackPeak: gg.P(4.0),
|
||||
RGAlbumGain: new(1.0), RGAlbumPeak: new(2.0), RGTrackGain: new(3.0), RGTrackPeak: new(4.0),
|
||||
})
|
||||
songAntennaWithLyrics = mf(model.MediaFile{
|
||||
ID: "1005",
|
||||
@@ -162,8 +161,6 @@ func p(path string) string {
|
||||
return filepath.FromSlash(path)
|
||||
}
|
||||
|
||||
// Initialize test DB
|
||||
// TODO Load this data setup from file(s)
|
||||
var _ = BeforeSuite(func() {
|
||||
conn := GetDBXBuilder()
|
||||
ctx := log.NewContext(context.TODO())
|
||||
@@ -187,8 +184,7 @@ var _ = BeforeSuite(func() {
|
||||
|
||||
alr := NewAlbumRepository(ctx, conn).(*albumRepository)
|
||||
for i := range testAlbums {
|
||||
a := testAlbums[i]
|
||||
err := alr.Put(&a)
|
||||
err := alr.Put(new(testAlbums[i]))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -196,8 +192,7 @@ var _ = BeforeSuite(func() {
|
||||
|
||||
arr := NewArtistRepository(ctx, conn)
|
||||
for i := range testArtists {
|
||||
a := testArtists[i]
|
||||
err := arr.Put(&a)
|
||||
err := arr.Put(new(testArtists[i]))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -243,8 +238,7 @@ var _ = BeforeSuite(func() {
|
||||
|
||||
rar := NewRadioRepository(ctx, conn)
|
||||
for i := range testRadios {
|
||||
r := testRadios[i]
|
||||
err := rar.Put(&r)
|
||||
err := rar.Put(new(testRadios[i]))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -89,8 +89,7 @@ func (r *playQueueRepository) Retrieve(userId string) (*model.PlayQueue, error)
|
||||
sel := r.newSelect().Columns("*").Where(Eq{"user_id": userId})
|
||||
var res playQueue
|
||||
err := r.queryOne(sel, &res)
|
||||
q := r.toModel(&res)
|
||||
return &q, err
|
||||
return new(r.toModel(&res)), err
|
||||
}
|
||||
|
||||
func (r *playQueueRepository) fromModel(q *model.PlayQueue) playQueue {
|
||||
|
||||
@@ -34,8 +34,7 @@ var _ = Describe("RadioRepository", func() {
|
||||
}
|
||||
|
||||
for i := range testRadios {
|
||||
r := testRadios[i]
|
||||
err := repo.Put(&r)
|
||||
err := repo.Put(new(testRadios[i]))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -37,8 +37,7 @@ var _ = Describe("KVStoreService", func() {
|
||||
conf.Server.DataFolder = conf.NewDir(tmpDir)
|
||||
|
||||
// Create service with 1KB limit for testing
|
||||
maxSize := "1KB"
|
||||
service, err = newKVStoreService(ctx, "test_plugin", &KVStorePermission{MaxSize: &maxSize})
|
||||
service, err = newKVStoreService(ctx, "test_plugin", &KVStorePermission{MaxSize: new("1KB")})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -253,8 +252,7 @@ var _ = Describe("KVStoreService", func() {
|
||||
// Close and reopen the service (simulating restart)
|
||||
Expect(service.Close()).To(Succeed())
|
||||
|
||||
maxSize := "1KB"
|
||||
service2, err := newKVStoreService(ctx, "test_plugin", &KVStorePermission{MaxSize: &maxSize})
|
||||
service2, err := newKVStoreService(ctx, "test_plugin", &KVStorePermission{MaxSize: new("1KB")})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer service2.Close()
|
||||
|
||||
@@ -452,8 +450,7 @@ var _ = Describe("KVStoreService", func() {
|
||||
closeCtx, closeCancel := context.WithCancel(ctx)
|
||||
defer closeCancel()
|
||||
|
||||
maxSize := "1KB"
|
||||
svc, err := newKVStoreService(closeCtx, "test_close_race", &KVStorePermission{MaxSize: &maxSize})
|
||||
svc, err := newKVStoreService(closeCtx, "test_close_race", &KVStorePermission{MaxSize: new("1KB")})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Insert an expired key so cleanup has work to do
|
||||
|
||||
@@ -35,8 +35,7 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
|
||||
Describe("GetLibrary", func() {
|
||||
It("should return library metadata without filesystem permission", func() {
|
||||
reason := "test"
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason, Filesystem: false}, nil, true).(*libraryServiceImpl)
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test"), Filesystem: false}, nil, true).(*libraryServiceImpl)
|
||||
|
||||
lib := &model.Library{
|
||||
ID: 1,
|
||||
@@ -67,8 +66,7 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
})
|
||||
|
||||
It("should return library metadata with filesystem permission", func() {
|
||||
reason := "test"
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason, Filesystem: true}, nil, true).(*libraryServiceImpl)
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test"), Filesystem: true}, nil, true).(*libraryServiceImpl)
|
||||
|
||||
lib := &model.Library{
|
||||
ID: 2,
|
||||
@@ -93,8 +91,7 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
})
|
||||
|
||||
It("should return error for non-existent library", func() {
|
||||
reason := "test"
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason}, nil, true).(*libraryServiceImpl)
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test")}, nil, true).(*libraryServiceImpl)
|
||||
|
||||
mockLibRepo := ds.Library(ctx).(*tests.MockLibraryRepo)
|
||||
mockLibRepo.SetData(model.Libraries{})
|
||||
@@ -107,8 +104,7 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
|
||||
Describe("GetAllLibraries", func() {
|
||||
It("should return all libraries without filesystem permission", func() {
|
||||
reason := "test"
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason, Filesystem: false}, nil, true).(*libraryServiceImpl)
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test"), Filesystem: false}, nil, true).(*libraryServiceImpl)
|
||||
|
||||
libs := model.Libraries{
|
||||
{ID: 1, Name: "Rock", Path: "/music/rock", TotalSongs: 100},
|
||||
@@ -130,8 +126,7 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
})
|
||||
|
||||
It("should return all libraries with filesystem permission", func() {
|
||||
reason := "test"
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason, Filesystem: true}, nil, true).(*libraryServiceImpl)
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test"), Filesystem: true}, nil, true).(*libraryServiceImpl)
|
||||
|
||||
libs := model.Libraries{
|
||||
{ID: 1, Name: "Rock", Path: "/music/rock", TotalSongs: 100},
|
||||
@@ -152,10 +147,8 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
})
|
||||
|
||||
Describe("Library Access Filtering", func() {
|
||||
It("should only return libraries in the allowed list", func() {
|
||||
reason := "test"
|
||||
// Only allow library ID 2
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason, Filesystem: false}, []int{2}, false).(*libraryServiceImpl)
|
||||
It("should only return libraries in the allowed list", func() { // Only allow library ID 2
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test"), Filesystem: false}, []int{2}, false).(*libraryServiceImpl)
|
||||
|
||||
libs := model.Libraries{
|
||||
{ID: 1, Name: "Rock", Path: "/music/rock", TotalSongs: 100},
|
||||
@@ -173,10 +166,8 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
Expect(results[0].Name).To(Equal("Jazz"))
|
||||
})
|
||||
|
||||
It("should return error when getting a library not in the allowed list", func() {
|
||||
reason := "test"
|
||||
// Only allow library ID 2
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason, Filesystem: false}, []int{2}, false).(*libraryServiceImpl)
|
||||
It("should return error when getting a library not in the allowed list", func() { // Only allow library ID 2
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test"), Filesystem: false}, []int{2}, false).(*libraryServiceImpl)
|
||||
|
||||
libs := model.Libraries{
|
||||
{ID: 1, Name: "Rock", Path: "/music/rock", TotalSongs: 100},
|
||||
@@ -192,10 +183,8 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
Expect(err.Error()).To(ContainSubstring("not accessible"))
|
||||
})
|
||||
|
||||
It("should allow access to a library in the allowed list", func() {
|
||||
reason := "test"
|
||||
// Only allow library ID 2
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason, Filesystem: false}, []int{2}, false).(*libraryServiceImpl)
|
||||
It("should allow access to a library in the allowed list", func() { // Only allow library ID 2
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test"), Filesystem: false}, []int{2}, false).(*libraryServiceImpl)
|
||||
|
||||
libs := model.Libraries{
|
||||
{ID: 1, Name: "Rock", Path: "/music/rock", TotalSongs: 100},
|
||||
@@ -211,10 +200,8 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
Expect(result.Name).To(Equal("Jazz"))
|
||||
})
|
||||
|
||||
It("should return empty list when no libraries are allowed and allLibraries is false", func() {
|
||||
reason := "test"
|
||||
// No libraries allowed
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason, Filesystem: false}, []int{}, false).(*libraryServiceImpl)
|
||||
It("should return empty list when no libraries are allowed and allLibraries is false", func() { // No libraries allowed
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test"), Filesystem: false}, []int{}, false).(*libraryServiceImpl)
|
||||
|
||||
libs := model.Libraries{
|
||||
{ID: 1, Name: "Rock", Path: "/music/rock", TotalSongs: 100},
|
||||
@@ -229,10 +216,8 @@ var _ = Describe("LibraryService", Ordered, func() {
|
||||
Expect(results).To(HaveLen(0))
|
||||
})
|
||||
|
||||
It("should return all libraries when allLibraries is true regardless of allowed list", func() {
|
||||
reason := "test"
|
||||
// allLibraries=true should ignore the allowed list
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: &reason, Filesystem: false}, []int{1}, true).(*libraryServiceImpl)
|
||||
It("should return all libraries when allLibraries is true regardless of allowed list", func() { // allLibraries=true should ignore the allowed list
|
||||
service = newLibraryService(ds, &LibraryPermission{Reason: new("test"), Filesystem: false}, []int{1}, true).(*libraryServiceImpl)
|
||||
|
||||
libs := model.Libraries{
|
||||
{ID: 1, Name: "Rock", Path: "/music/rock", TotalSongs: 100},
|
||||
|
||||
@@ -302,8 +302,7 @@ func (s *webSocketServiceImpl) readLoop(ctx context.Context, connectionID string
|
||||
if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway, websocket.CloseNoStatusReceived) {
|
||||
closeCode := websocket.CloseNoStatusReceived
|
||||
closeReason := ""
|
||||
var ce *websocket.CloseError
|
||||
if errors.As(err, &ce) {
|
||||
if ce, ok := errors.AsType[*websocket.CloseError](err); ok {
|
||||
closeCode = ce.Code
|
||||
closeReason = ce.Text
|
||||
}
|
||||
|
||||
@@ -140,11 +140,10 @@ var _ = Describe("Manifest", func() {
|
||||
})
|
||||
|
||||
It("returns true when threads feature has a reason", func() {
|
||||
reason := "Required for concurrent processing"
|
||||
m := &Manifest{
|
||||
Experimental: &Experimental{
|
||||
Threads: &ThreadsFeature{
|
||||
Reason: &reason,
|
||||
Reason: new("Required for concurrent processing"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -135,12 +135,11 @@ var _ = Describe("ndpPackage", func() {
|
||||
Describe("readManifest", func() {
|
||||
It("should read only the manifest without loading wasm", func() {
|
||||
ndpPath := filepath.Join(tmpDir, "test.ndp")
|
||||
desc := "A test plugin"
|
||||
manifest := &Manifest{
|
||||
Name: "Test Plugin",
|
||||
Author: "Test Author",
|
||||
Version: "1.0.0",
|
||||
Description: &desc,
|
||||
Description: new("A test plugin"),
|
||||
}
|
||||
wasmBytes := make([]byte, 1024*1024) // 1MB of zeros
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/request"
|
||||
"github.com/navidrome/navidrome/server/events"
|
||||
. "github.com/navidrome/navidrome/utils/gg"
|
||||
"github.com/navidrome/navidrome/utils/pl"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
@@ -38,7 +37,7 @@ func New(rootCtx context.Context, ds model.DataStore, cw artwork.CacheWarmer, br
|
||||
devExternalScanner: conf.Server.DevExternalScanner,
|
||||
}
|
||||
if !c.devExternalScanner {
|
||||
c.limiter = P(rate.Sometimes{Interval: conf.Server.DevActivityPanelUpdateRate})
|
||||
c.limiter = new(rate.Sometimes{Interval: conf.Server.DevActivityPanelUpdateRate})
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
+1
-2
@@ -97,8 +97,7 @@ func (s *scannerExternal) scan(ctx context.Context, fullScan bool, targets []mod
|
||||
|
||||
func (s *scannerExternal) wait(cmd *exec.Cmd, out *io.PipeWriter) {
|
||||
if err := cmd.Wait(); err != nil {
|
||||
var exitErr *exec.ExitError
|
||||
if errors.As(err, &exitErr) {
|
||||
if exitErr, ok := errors.AsType[*exec.ExitError](err); ok {
|
||||
_ = out.CloseWithError(fmt.Errorf("%s exited with non-zero status code: %w", cmd, exitErr))
|
||||
} else {
|
||||
_ = out.CloseWithError(fmt.Errorf("waiting %s cmd: %w", cmd, err))
|
||||
|
||||
+1
-2
@@ -135,7 +135,6 @@ func createAdmin(ds model.DataStore) func(w http.ResponseWriter, r *http.Request
|
||||
|
||||
func createAdminUser(ctx context.Context, ds model.DataStore, username, password string) error {
|
||||
log.Warn(ctx, "Creating initial user", "user", username)
|
||||
now := time.Now()
|
||||
caser := cases.Title(language.Und)
|
||||
initialUser := model.User{
|
||||
ID: id.NewRandom(),
|
||||
@@ -144,7 +143,7 @@ func createAdminUser(ctx context.Context, ds model.DataStore, username, password
|
||||
Email: "",
|
||||
NewPassword: password,
|
||||
IsAdmin: true,
|
||||
LastLoginAt: &now,
|
||||
LastLoginAt: new(time.Now()),
|
||||
}
|
||||
err := ds.User(ctx).Put(&initialUser)
|
||||
if err != nil {
|
||||
|
||||
@@ -45,8 +45,7 @@ func (api *Router) uploadArtistImage() http.HandlerFunc {
|
||||
return err
|
||||
}
|
||||
ar.UploadedImage = filename
|
||||
now := time.Now()
|
||||
ar.UpdatedAt = &now
|
||||
ar.UpdatedAt = new(time.Now())
|
||||
return api.ds.Artist(ctx).Put(ar, "uploaded_image", "updated_at")
|
||||
})
|
||||
}
|
||||
@@ -65,8 +64,7 @@ func (api *Router) deleteArtistImage() http.HandlerFunc {
|
||||
return err
|
||||
}
|
||||
ar.UploadedImage = ""
|
||||
now := time.Now()
|
||||
ar.UpdatedAt = &now
|
||||
ar.UpdatedAt = new(time.Now())
|
||||
return api.ds.Artist(ctx).Put(ar, "uploaded_image", "updated_at")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/request"
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -32,7 +31,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
|
||||
Describe("POST /queue", func() {
|
||||
It("saves the queue", func() {
|
||||
payload := updateQueuePayload{Ids: gg.P([]string{"s1", "s2"}), Current: gg.P(1), Position: gg.P(int64(10))}
|
||||
payload := updateQueuePayload{Ids: new([]string{"s1", "s2"}), Current: new(1), Position: new(int64(10))}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("POST", "/queue", bytes.NewReader(body))
|
||||
ctx := request.WithUser(req.Context(), user)
|
||||
@@ -50,7 +49,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
})
|
||||
|
||||
It("saves an empty queue", func() {
|
||||
payload := updateQueuePayload{Ids: gg.P([]string{}), Current: gg.P(0), Position: gg.P(int64(0))}
|
||||
payload := updateQueuePayload{Ids: new([]string{}), Current: new(0), Position: new(int64(0))}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("POST", "/queue", bytes.NewReader(body))
|
||||
req = req.WithContext(request.WithUser(req.Context(), user))
|
||||
@@ -63,7 +62,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
})
|
||||
|
||||
It("returns bad request for invalid current index (negative)", func() {
|
||||
payload := updateQueuePayload{Ids: gg.P([]string{"s1", "s2"}), Current: gg.P(-1), Position: gg.P(int64(10))}
|
||||
payload := updateQueuePayload{Ids: new([]string{"s1", "s2"}), Current: new(-1), Position: new(int64(10))}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("POST", "/queue", bytes.NewReader(body))
|
||||
req = req.WithContext(request.WithUser(req.Context(), user))
|
||||
@@ -75,7 +74,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
})
|
||||
|
||||
It("returns bad request for invalid current index (too large)", func() {
|
||||
payload := updateQueuePayload{Ids: gg.P([]string{"s1", "s2"}), Current: gg.P(2), Position: gg.P(int64(10))}
|
||||
payload := updateQueuePayload{Ids: new([]string{"s1", "s2"}), Current: new(2), Position: new(int64(10))}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("POST", "/queue", bytes.NewReader(body))
|
||||
req = req.WithContext(request.WithUser(req.Context(), user))
|
||||
@@ -97,7 +96,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
|
||||
It("returns internal server error when store fails", func() {
|
||||
repo.Err = true
|
||||
payload := updateQueuePayload{Ids: gg.P([]string{"s1"}), Current: gg.P(0), Position: gg.P(int64(10))}
|
||||
payload := updateQueuePayload{Ids: new([]string{"s1"}), Current: new(0), Position: new(int64(10))}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("POST", "/queue", bytes.NewReader(body))
|
||||
req = req.WithContext(request.WithUser(req.Context(), user))
|
||||
@@ -166,7 +165,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
Describe("PUT /queue", func() {
|
||||
It("updates the queue fields", func() {
|
||||
repo.Queue = &model.PlayQueue{UserID: user.ID, Items: model.MediaFiles{{ID: "s1"}, {ID: "s2"}, {ID: "s3"}}}
|
||||
payload := updateQueuePayload{Current: gg.P(2), Position: gg.P(int64(20))}
|
||||
payload := updateQueuePayload{Current: new(2), Position: new(int64(20))}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("PUT", "/queue", bytes.NewReader(body))
|
||||
ctx := request.WithUser(req.Context(), user)
|
||||
@@ -184,7 +183,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
|
||||
It("updates only ids", func() {
|
||||
repo.Queue = &model.PlayQueue{UserID: user.ID, Current: 1}
|
||||
payload := updateQueuePayload{Ids: gg.P([]string{"s1", "s2"})}
|
||||
payload := updateQueuePayload{Ids: new([]string{"s1", "s2"})}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("PUT", "/queue", bytes.NewReader(body))
|
||||
req = req.WithContext(request.WithUser(req.Context(), user))
|
||||
@@ -198,7 +197,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
|
||||
It("updates ids and current", func() {
|
||||
repo.Queue = &model.PlayQueue{UserID: user.ID}
|
||||
payload := updateQueuePayload{Ids: gg.P([]string{"s1", "s2"}), Current: gg.P(1)}
|
||||
payload := updateQueuePayload{Ids: new([]string{"s1", "s2"}), Current: new(1)}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("PUT", "/queue", bytes.NewReader(body))
|
||||
req = req.WithContext(request.WithUser(req.Context(), user))
|
||||
@@ -213,7 +212,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
|
||||
It("returns bad request when new ids invalidate current", func() {
|
||||
repo.Queue = &model.PlayQueue{UserID: user.ID, Current: 2}
|
||||
payload := updateQueuePayload{Ids: gg.P([]string{"s1", "s2"})}
|
||||
payload := updateQueuePayload{Ids: new([]string{"s1", "s2"})}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("PUT", "/queue", bytes.NewReader(body))
|
||||
req = req.WithContext(request.WithUser(req.Context(), user))
|
||||
@@ -225,7 +224,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
|
||||
It("returns bad request when current out of bounds", func() {
|
||||
repo.Queue = &model.PlayQueue{UserID: user.ID, Items: model.MediaFiles{{ID: "s1"}}}
|
||||
payload := updateQueuePayload{Current: gg.P(3)}
|
||||
payload := updateQueuePayload{Current: new(3)}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("PUT", "/queue", bytes.NewReader(body))
|
||||
req = req.WithContext(request.WithUser(req.Context(), user))
|
||||
@@ -246,7 +245,7 @@ var _ = Describe("Queue Endpoints", func() {
|
||||
|
||||
It("returns internal server error when store fails", func() {
|
||||
repo.Err = true
|
||||
payload := updateQueuePayload{Position: gg.P(int64(10))}
|
||||
payload := updateQueuePayload{Position: new(int64(10))}
|
||||
body, _ := json.Marshal(payload)
|
||||
req := httptest.NewRequest("PUT", "/queue", bytes.NewReader(body))
|
||||
req = req.WithContext(request.WithUser(req.Context(), user))
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/navidrome/navidrome/core/stream"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
. "github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -89,7 +88,7 @@ var _ = Describe("encodeMediafileShare", func() {
|
||||
})
|
||||
|
||||
It("includes the share ID in the token", func() {
|
||||
exp := P(time.Now().Add(time.Hour))
|
||||
exp := new(time.Now().Add(time.Hour))
|
||||
s := model.Share{ID: "shareABC", Format: "mp3", MaxBitRate: 320, ExpiresAt: exp}
|
||||
token := encodeMediafileShare(s, "mf-999")
|
||||
info, err := decodeStreamInfo(token)
|
||||
@@ -164,8 +163,7 @@ var _ = Describe("handleStream", func() {
|
||||
|
||||
It("returns 410 when share has been set to expired", func() {
|
||||
shareRepo.ID = "share123"
|
||||
expired := time.Now().Add(-time.Hour)
|
||||
shareRepo.Entity = &model.Share{ID: "share123", ExpiresAt: &expired}
|
||||
shareRepo.Entity = &model.Share{ID: "share123", ExpiresAt: new(time.Now().Add(-time.Hour))}
|
||||
|
||||
claims := auth.Claims{ID: "mf-123", ShareID: "share123"}
|
||||
token, _ := auth.CreatePublicToken(claims)
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/navidrome/navidrome/server/subsonic/responses"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"golang.org/x/net/context"
|
||||
@@ -136,7 +135,7 @@ var _ = Describe("sendResponse", func() {
|
||||
It("should return a fail response", func() {
|
||||
payload.Song = &responses.Child{OpenSubsonicChild: &responses.OpenSubsonicChild{}}
|
||||
// An +Inf value will cause an error when marshalling to JSON
|
||||
payload.Song.ReplayGain = responses.ReplayGain{TrackGain: gg.P(math.Inf(1))}
|
||||
payload.Song.ReplayGain = responses.ReplayGain{TrackGain: new(math.Inf(1))}
|
||||
q := r.URL.Query()
|
||||
q.Add("f", "json")
|
||||
r.URL.RawQuery = q.Encode()
|
||||
|
||||
@@ -256,8 +256,7 @@ func (api *Router) GetSong(r *http.Request) (*responses.Subsonic, error) {
|
||||
}
|
||||
|
||||
response := newResponse()
|
||||
child := childFromMediaFile(ctx, *mf)
|
||||
response.Song = &child
|
||||
response.Song = new(childFromMediaFile(ctx, *mf))
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/request"
|
||||
"github.com/navidrome/navidrome/server/subsonic/responses"
|
||||
. "github.com/navidrome/navidrome/utils/gg"
|
||||
"github.com/navidrome/navidrome/utils/number"
|
||||
"github.com/navidrome/navidrome/utils/req"
|
||||
"github.com/navidrome/navidrome/utils/slice"
|
||||
@@ -217,7 +216,7 @@ func childFromMediaFile(ctx context.Context, mf model.MediaFile) responses.Child
|
||||
child.Path = fakePath(mf)
|
||||
}
|
||||
child.DiscNumber = int32(mf.DiscNumber)
|
||||
child.Created = P(mf.BirthTime)
|
||||
child.Created = new(mf.BirthTime)
|
||||
child.AlbumId = mf.AlbumID
|
||||
child.ArtistId = mf.ArtistID
|
||||
child.Type = "music"
|
||||
@@ -346,7 +345,7 @@ func childFromAlbum(ctx context.Context, al model.Album) responses.Child {
|
||||
child.Year = int32(cmp.Or(al.MaxOriginalYear, al.MaxYear))
|
||||
child.Genre = al.Genre
|
||||
child.CoverArt = al.CoverArtID().String()
|
||||
child.Created = P(albumCreatedAt(al))
|
||||
child.Created = new(albumCreatedAt(al))
|
||||
child.Parent = al.AlbumArtistID
|
||||
child.ArtistId = al.AlbumArtistID
|
||||
child.Duration = int32(al.Duration)
|
||||
@@ -442,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 = P(albumCreatedAt(album))
|
||||
dir.Created = new(albumCreatedAt(album))
|
||||
if album.Starred {
|
||||
dir.Starred = album.StarredAt
|
||||
}
|
||||
|
||||
@@ -294,7 +294,6 @@ var _ = Describe("MediaRetrievalController", func() {
|
||||
response, err := router.GetLyricsBySongId(r)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
offset := int64(-100)
|
||||
compareResponses(response.LyricsList, responses.LyricsList{
|
||||
StructuredLyrics: responses.StructuredLyrics{
|
||||
{
|
||||
@@ -312,7 +311,7 @@ var _ = Describe("MediaRetrievalController", func() {
|
||||
Value: "You know the rules and so do I",
|
||||
},
|
||||
},
|
||||
Offset: &offset,
|
||||
Offset: new(int64(-100)),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/request"
|
||||
"github.com/navidrome/navidrome/server/subsonic/responses"
|
||||
. "github.com/navidrome/navidrome/utils/gg"
|
||||
"github.com/navidrome/navidrome/utils/req"
|
||||
"github.com/navidrome/navidrome/utils/slice"
|
||||
)
|
||||
@@ -169,7 +168,7 @@ func buildOSPlaylist(ctx context.Context, p model.Playlist) *responses.OpenSubso
|
||||
pls.Readonly = true
|
||||
|
||||
if p.EvaluatedAt != nil {
|
||||
pls.ValidUntil = P(p.EvaluatedAt.Add(conf.Server.SmartPlaylistRefreshDelay))
|
||||
pls.ValidUntil = new(p.EvaluatedAt.Add(conf.Server.SmartPlaylistRefreshDelay))
|
||||
}
|
||||
} else {
|
||||
user, ok := request.UserFrom(ctx)
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/server/subsonic/responses"
|
||||
. "github.com/navidrome/navidrome/server/subsonic/responses"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -94,11 +93,10 @@ var _ = Describe("Responses", func() {
|
||||
Context("with data", func() {
|
||||
BeforeEach(func() {
|
||||
artists := make([]Artist, 1)
|
||||
t := time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)
|
||||
artists[0] = Artist{
|
||||
Id: "111",
|
||||
Name: "aaa",
|
||||
Starred: &t,
|
||||
Starred: new(time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)),
|
||||
UserRating: 3,
|
||||
ArtistImageUrl: "https://lastfm.freetls.fastly.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
|
||||
}
|
||||
@@ -133,11 +131,10 @@ var _ = Describe("Responses", func() {
|
||||
Context("with data", func() {
|
||||
BeforeEach(func() {
|
||||
artists := make([]ArtistID3, 1)
|
||||
t := time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)
|
||||
artists[0] = ArtistID3{
|
||||
Id: "111",
|
||||
Name: "aaa",
|
||||
Starred: &t,
|
||||
Starred: new(time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)),
|
||||
UserRating: 3,
|
||||
AlbumCount: 2,
|
||||
ArtistImageUrl: "https://lastfm.freetls.fastly.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
|
||||
@@ -158,11 +155,10 @@ var _ = Describe("Responses", func() {
|
||||
Context("with OpenSubsonic data", func() {
|
||||
BeforeEach(func() {
|
||||
artists := make([]ArtistID3, 1)
|
||||
t := time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)
|
||||
artists[0] = ArtistID3{
|
||||
Id: "111",
|
||||
Name: "aaa",
|
||||
Starred: &t,
|
||||
Starred: new(time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)),
|
||||
UserRating: 3,
|
||||
AlbumCount: 2,
|
||||
ArtistImageUrl: "https://lastfm.freetls.fastly.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
|
||||
@@ -211,12 +207,11 @@ var _ = Describe("Responses", func() {
|
||||
BeforeEach(func() {
|
||||
response.Directory = &Directory{Id: "1", Name: "N"}
|
||||
child := make([]Child, 2)
|
||||
t := time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)
|
||||
child[0] = Child{
|
||||
Id: "1", IsDir: true, Title: "title", Album: "album", Artist: "artist", Track: 1,
|
||||
Year: 1985, Genre: "Rock", CoverArt: "1", Size: 8421341, ContentType: "audio/flac",
|
||||
Suffix: "flac", TranscodedContentType: "audio/mpeg", TranscodedSuffix: "mp3",
|
||||
Duration: 146, BitRate: 320, Starred: &t,
|
||||
Duration: 146, BitRate: 320, Starred: new(time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)),
|
||||
}
|
||||
child[0].OpenSubsonicChild = &OpenSubsonicChild{
|
||||
Genres: []ItemGenre{{Name: "rock"}, {Name: "progressive"}},
|
||||
@@ -225,7 +220,7 @@ var _ = Describe("Responses", func() {
|
||||
BPM: 127, ChannelCount: 2, SamplingRate: 44100, BitDepth: 16,
|
||||
Moods: []string{"happy", "sad"},
|
||||
Groupings: []string{"Soundtrack", "Live"},
|
||||
ReplayGain: ReplayGain{TrackGain: gg.P(1.0), AlbumGain: gg.P(2.0), TrackPeak: gg.P(3.0), AlbumPeak: gg.P(4.0), BaseGain: gg.P(5.0), FallbackGain: gg.P(6.0)},
|
||||
ReplayGain: ReplayGain{TrackGain: new(1.0), AlbumGain: new(2.0), TrackPeak: new(3.0), AlbumPeak: new(4.0), BaseGain: new(5.0), FallbackGain: new(6.0)},
|
||||
DisplayArtist: "artist 1 & artist 2",
|
||||
Artists: []ArtistID3Ref{
|
||||
{Id: "1", Name: "artist1"},
|
||||
@@ -246,7 +241,7 @@ var _ = Describe("Responses", func() {
|
||||
ExplicitStatus: "clean",
|
||||
}
|
||||
child[1].OpenSubsonicChild = &OpenSubsonicChild{
|
||||
ReplayGain: ReplayGain{TrackGain: gg.P(0.0), AlbumGain: gg.P(0.0), TrackPeak: gg.P(0.0), AlbumPeak: gg.P(0.0), BaseGain: gg.P(0.0), FallbackGain: gg.P(0.0)},
|
||||
ReplayGain: ReplayGain{TrackGain: new(0.0), AlbumGain: new(0.0), TrackPeak: new(0.0), AlbumPeak: new(0.0), BaseGain: new(0.0), FallbackGain: new(0.0)},
|
||||
}
|
||||
response.Directory.Child = child
|
||||
})
|
||||
@@ -322,7 +317,7 @@ var _ = Describe("Responses", func() {
|
||||
Isrc: []string{"ISRC-1"},
|
||||
Moods: []string{"happy", "sad"},
|
||||
Groupings: []string{"Soundtrack", "Live"},
|
||||
ReplayGain: ReplayGain{TrackGain: gg.P(1.0), AlbumGain: gg.P(2.0), TrackPeak: gg.P(3.0), AlbumPeak: gg.P(4.0), BaseGain: gg.P(5.0), FallbackGain: gg.P(6.0)},
|
||||
ReplayGain: ReplayGain{TrackGain: new(1.0), AlbumGain: new(2.0), TrackPeak: new(3.0), AlbumPeak: new(4.0), BaseGain: new(5.0), FallbackGain: new(6.0)},
|
||||
BPM: 127, ChannelCount: 2, SamplingRate: 44100, BitDepth: 16,
|
||||
DisplayArtist: "artist1 & artist2",
|
||||
Artists: []ArtistID3Ref{
|
||||
@@ -342,7 +337,7 @@ var _ = Describe("Responses", func() {
|
||||
ExplicitStatus: "clean",
|
||||
}
|
||||
songs[1].OpenSubsonicChild = &OpenSubsonicChild{
|
||||
ReplayGain: ReplayGain{TrackGain: gg.P(0.0), AlbumGain: gg.P(0.0), TrackPeak: gg.P(0.0), AlbumPeak: gg.P(0.0), BaseGain: gg.P(0.0), FallbackGain: gg.P(0.0)},
|
||||
ReplayGain: ReplayGain{TrackGain: new(0.0), AlbumGain: new(0.0), TrackPeak: new(0.0), AlbumPeak: new(0.0), BaseGain: new(0.0), FallbackGain: new(0.0)},
|
||||
}
|
||||
response.AlbumWithSongsID3.AlbumID3 = album
|
||||
response.AlbumWithSongsID3.Song = songs
|
||||
@@ -804,7 +799,7 @@ var _ = Describe("Responses", func() {
|
||||
Context("with data", func() {
|
||||
BeforeEach(func() {
|
||||
response.PlayQueueByIndex.Username = "user1"
|
||||
response.PlayQueueByIndex.CurrentIndex = gg.P(0)
|
||||
response.PlayQueueByIndex.CurrentIndex = new(0)
|
||||
response.PlayQueueByIndex.Position = 243
|
||||
response.PlayQueueByIndex.Changed = time.Time{}
|
||||
response.PlayQueueByIndex.ChangedBy = "a_client"
|
||||
|
||||
@@ -58,12 +58,10 @@ func (api *Router) CreateShare(r *http.Request) (*responses.Subsonic, error) {
|
||||
}
|
||||
|
||||
description, _ := p.String("description")
|
||||
expires := p.TimeOr("expires", time.Time{})
|
||||
|
||||
repo := api.share.NewRepository(r.Context())
|
||||
share := &model.Share{
|
||||
Description: description,
|
||||
ExpiresAt: &expires,
|
||||
ExpiresAt: new(p.TimeOr("expires", time.Time{})),
|
||||
ResourceIDs: strings.Join(ids, ","),
|
||||
}
|
||||
|
||||
@@ -90,13 +88,11 @@ func (api *Router) UpdateShare(r *http.Request) (*responses.Subsonic, error) {
|
||||
}
|
||||
|
||||
description, _ := p.String("description")
|
||||
expires := p.TimeOr("expires", time.Time{})
|
||||
|
||||
repo := api.share.NewRepository(r.Context())
|
||||
share := &model.Share{
|
||||
ID: id,
|
||||
Description: description,
|
||||
ExpiresAt: &expires,
|
||||
ExpiresAt: new(p.TimeOr("expires", time.Time{})),
|
||||
}
|
||||
|
||||
err = repo.(rest.Persistable).Update(id, share)
|
||||
|
||||
@@ -46,8 +46,7 @@ func (api *Router) GetUser(r *http.Request) (*responses.Subsonic, error) {
|
||||
return nil, newError(responses.ErrorAuthorizationFail)
|
||||
}
|
||||
response := newResponse()
|
||||
user := buildUserResponse(loggedUser)
|
||||
response.User = &user
|
||||
response.User = new(buildUserResponse(loggedUser))
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
)
|
||||
|
||||
func CreateMockUserRepo() *MockedUserRepo {
|
||||
@@ -84,7 +83,7 @@ func (u *MockedUserRepo) GetAll(options ...model.QueryOptions) (model.Users, err
|
||||
func (u *MockedUserRepo) UpdateLastLoginAt(id string) error {
|
||||
for _, usr := range u.Data {
|
||||
if usr.ID == id {
|
||||
usr.LastLoginAt = gg.P(time.Now())
|
||||
usr.LastLoginAt = new(time.Now())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -94,7 +93,7 @@ func (u *MockedUserRepo) UpdateLastLoginAt(id string) error {
|
||||
func (u *MockedUserRepo) UpdateLastAccessAt(id string) error {
|
||||
for _, usr := range u.Data {
|
||||
if usr.ID == id {
|
||||
usr.LastAccessAt = gg.P(time.Now())
|
||||
usr.LastAccessAt = new(time.Now())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-2
@@ -75,8 +75,7 @@ func (c *HTTPClient) serializeReq(req *http.Request) string {
|
||||
}
|
||||
if req.Body != nil {
|
||||
bodyData, _ := io.ReadAll(req.Body)
|
||||
bodyStr := base64.StdEncoding.EncodeToString(bodyData)
|
||||
data.Body = &bodyStr
|
||||
data.Body = new(base64.StdEncoding.EncodeToString(bodyData))
|
||||
}
|
||||
j, _ := json.Marshal(&data)
|
||||
return string(j)
|
||||
|
||||
Vendored
+1
-2
@@ -9,7 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/jellydator/ttlcache/v3"
|
||||
. "github.com/navidrome/navidrome/utils/gg"
|
||||
)
|
||||
|
||||
type SimpleCache[K comparable, V any] interface {
|
||||
@@ -119,7 +118,7 @@ func (c *simpleCache[K, V]) GetWithLoader(key K, loader func(key K) (V, time.Dur
|
||||
func (c *simpleCache[K, V]) evictExpired() {
|
||||
if c.evictionDeadline.Load() == nil || c.evictionDeadline.Load().Before(time.Now()) {
|
||||
c.data.DeleteExpired()
|
||||
c.evictionDeadline.Store(P(time.Now().Add(evictionTimeout)))
|
||||
c.evictionDeadline.Store(new(time.Now().Add(evictionTimeout)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ package chrono
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
. "github.com/navidrome/navidrome/utils/gg"
|
||||
)
|
||||
|
||||
// Meter is a simple stopwatch
|
||||
@@ -13,7 +11,7 @@ type Meter struct {
|
||||
}
|
||||
|
||||
func (m *Meter) Start() {
|
||||
m.mark = P(time.Now())
|
||||
m.mark = new(time.Now())
|
||||
}
|
||||
|
||||
func (m *Meter) Stop() time.Duration {
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
// Package gg implements simple "extensions" to Go language. Based on https://github.com/icza/gog
|
||||
package gg
|
||||
|
||||
// P returns a pointer to the input value
|
||||
func P[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
// V returns the value of the input pointer, or a zero value if the input pointer is nil.
|
||||
func V[T any](p *T) T {
|
||||
if p == nil {
|
||||
|
||||
+1
-14
@@ -16,22 +16,9 @@ func TestGG(t *testing.T) {
|
||||
}
|
||||
|
||||
var _ = Describe("GG", func() {
|
||||
Describe("P", func() {
|
||||
It("returns a pointer to the input value", func() {
|
||||
v := 123
|
||||
Expect(gg.P(123)).To(Equal(&v))
|
||||
})
|
||||
|
||||
It("returns nil if the input value is zero", func() {
|
||||
v := 0
|
||||
Expect(gg.P(0)).To(Equal(&v))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("V", func() {
|
||||
It("returns the value of the input pointer", func() {
|
||||
v := 123
|
||||
Expect(gg.V(&v)).To(Equal(123))
|
||||
Expect(gg.V(new(123))).To(Equal(123))
|
||||
})
|
||||
|
||||
It("returns a zero value if the input pointer is nil", func() {
|
||||
|
||||
+2
-4
@@ -38,8 +38,7 @@ func (r *Values) String(param string) (string, error) {
|
||||
func (r *Values) StringPtr(param string) *string {
|
||||
var v *string
|
||||
if _, exists := r.URL.Query()[param]; exists {
|
||||
s := r.URL.Query().Get(param)
|
||||
v = &s
|
||||
v = new(r.URL.Query().Get(param))
|
||||
}
|
||||
return v
|
||||
}
|
||||
@@ -48,8 +47,7 @@ func (r *Values) BoolPtr(param string) *bool {
|
||||
var v *bool
|
||||
if _, exists := r.URL.Query()[param]; exists {
|
||||
s := r.URL.Query().Get(param)
|
||||
b := strings.Contains("/true/on/1/", "/"+strings.ToLower(s)+"/")
|
||||
v = &b
|
||||
v = new(strings.Contains("/true/on/1/", "/"+strings.ToLower(s)+"/"))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user