feat(insights): add file suffix counting

This commit is contained in:
Deluan
2026-01-18 17:00:35 -05:00
parent 2de2484bca
commit 0473c50b49
5 changed files with 63 additions and 0 deletions
+4
View File
@@ -265,6 +265,10 @@ func (c *insightsCollector) collect(ctx context.Context) []byte {
if err != nil {
log.Trace(ctx, "Error reading active users count", err)
}
data.Library.FileSuffixes, err = c.ds.MediaFile(ctx).CountBySuffix()
if err != nil {
log.Trace(ctx, "Error reading file suffixes count", err)
}
// Check for smart playlists
data.Config.HasSmartPlaylists, err = c.hasSmartPlaylists(ctx)
+1
View File
@@ -40,6 +40,7 @@ type Data struct {
Libraries int64 `json:"libraries"`
ActiveUsers int64 `json:"activeUsers"`
ActivePlayers map[string]int64 `json:"activePlayers,omitempty"`
FileSuffixes map[string]int64 `json:"fileSuffixes,omitempty"`
} `json:"library"`
Config struct {
LogLevel string `json:"logLevel,omitempty"`
+1
View File
@@ -353,6 +353,7 @@ type MediaFileCursor iter.Seq2[MediaFile, error]
type MediaFileRepository interface {
CountAll(options ...QueryOptions) (int64, error)
CountBySuffix(options ...QueryOptions) (map[string]int64, error)
Exists(id string) (bool, error)
Put(m *MediaFile) error
Get(id string) (*MediaFile, error)
+19
View File
@@ -124,6 +124,25 @@ func (r *mediaFileRepository) CountAll(options ...model.QueryOptions) (int64, er
return r.count(query, options...)
}
func (r *mediaFileRepository) CountBySuffix(options ...model.QueryOptions) (map[string]int64, error) {
sel := r.newSelect(options...).
Columns("lower(suffix) as suffix", "count(*) as count").
GroupBy("lower(suffix)")
var res []struct {
Suffix string
Count int64
}
err := r.queryAll(sel, &res)
if err != nil {
return nil, err
}
counts := make(map[string]int64, len(res))
for _, c := range res {
counts[c.Suffix] = c.Count
}
return counts, nil
}
func (r *mediaFileRepository) Exists(id string) (bool, error) {
return r.exists(Eq{"media_file.id": id})
}
+38
View File
@@ -41,6 +41,44 @@ var _ = Describe("MediaRepository", func() {
Expect(mr.CountAll()).To(Equal(int64(10)))
})
Describe("CountBySuffix", func() {
var mp3File, flacFile1, flacFile2, flacUpperFile model.MediaFile
BeforeEach(func() {
mp3File = model.MediaFile{ID: "suffix-mp3", LibraryID: 1, Suffix: "mp3", Path: "/test/file.mp3"}
flacFile1 = model.MediaFile{ID: "suffix-flac1", LibraryID: 1, Suffix: "flac", Path: "/test/file1.flac"}
flacFile2 = model.MediaFile{ID: "suffix-flac2", LibraryID: 1, Suffix: "flac", Path: "/test/file2.flac"}
flacUpperFile = model.MediaFile{ID: "suffix-FLAC", LibraryID: 1, Suffix: "FLAC", Path: "/test/file.FLAC"}
Expect(mr.Put(&mp3File)).To(Succeed())
Expect(mr.Put(&flacFile1)).To(Succeed())
Expect(mr.Put(&flacFile2)).To(Succeed())
Expect(mr.Put(&flacUpperFile)).To(Succeed())
})
AfterEach(func() {
_ = mr.Delete(mp3File.ID)
_ = mr.Delete(flacFile1.ID)
_ = mr.Delete(flacFile2.ID)
_ = mr.Delete(flacUpperFile.ID)
})
It("counts media files grouped by suffix with lowercase normalization", func() {
counts, err := mr.CountBySuffix()
Expect(err).ToNot(HaveOccurred())
// Should have lowercase keys only
Expect(counts).To(HaveKey("mp3"))
Expect(counts).To(HaveKey("flac"))
Expect(counts).ToNot(HaveKey("FLAC"))
// mp3: 1 file
Expect(counts["mp3"]).To(Equal(int64(1)))
// flac: 3 files (2 lowercase + 1 uppercase normalized)
Expect(counts["flac"]).To(Equal(int64(3)))
})
})
It("returns songs ordered by lyrics with a specific title/artist", func() {
// attempt to mimic filters.SongsByArtistTitleWithLyricsFirst, except we want all items
results, err := mr.GetAll(model.QueryOptions{