mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-31 07:30:32 +00:00
refactor(smartplaylists): make NormalizeChildPaths non-mutating
Signed-off-by: David <dvedvick@gmail.com>
This commit is contained in:
parent
8877d06b5c
commit
4bac694669
@ -1,6 +1,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strconv"
|
||||
@ -118,52 +119,70 @@ func (pls Playlist) UploadedImagePath() string {
|
||||
return UploadedImagePath(consts.EntityPlaylist, pls.UploadedImage)
|
||||
}
|
||||
|
||||
func (pls *Playlist) NormalizeChildPaths() {
|
||||
func (pls Playlist) WithNormalizeChildPaths() Playlist {
|
||||
if pls.Rules == nil || pls.Rules.Expression == nil {
|
||||
return
|
||||
return pls
|
||||
}
|
||||
|
||||
normalizePlaylistPaths(pls.Rules.Expression, pls.Path)
|
||||
plsClone := pls
|
||||
plsClone.Rules = &criteria.Criteria{
|
||||
Sort: pls.Rules.Sort,
|
||||
Limit: pls.Rules.Limit,
|
||||
LimitPercent: pls.Rules.LimitPercent,
|
||||
Offset: pls.Rules.Offset,
|
||||
Order: pls.Rules.Order,
|
||||
Expression: normalizePlaylistPaths(pls.Rules.Expression, pls.Path),
|
||||
}
|
||||
return plsClone
|
||||
}
|
||||
|
||||
func normalizePlaylistPaths(inputRule any, referencingPlaylistPath string) {
|
||||
func normalizePlaylistPaths(inputRule criteria.Expression, referencingPlaylistPath string) criteria.Expression {
|
||||
if referencingPlaylistPath == "" {
|
||||
return
|
||||
return inputRule
|
||||
}
|
||||
|
||||
switch rule := inputRule.(type) {
|
||||
case criteria.Any:
|
||||
for _, rules := range rule {
|
||||
normalizePlaylistPaths(rules, referencingPlaylistPath)
|
||||
anyCriteria := make(criteria.Any, len(rule))
|
||||
for i, rules := range rule {
|
||||
anyCriteria[i] = normalizePlaylistPaths(rules, referencingPlaylistPath)
|
||||
}
|
||||
return anyCriteria
|
||||
case criteria.All:
|
||||
for _, rules := range rule {
|
||||
normalizePlaylistPaths(rules, referencingPlaylistPath)
|
||||
allCriteria := make(criteria.All, len(rule))
|
||||
for i, rules := range rule {
|
||||
allCriteria[i] = normalizePlaylistPaths(rules, referencingPlaylistPath)
|
||||
}
|
||||
return allCriteria
|
||||
case criteria.InPlaylist:
|
||||
dir := filepath.Dir(referencingPlaylistPath)
|
||||
inPlaylist := maps.Clone(rule)
|
||||
if path, ok := rule["path"].(string); ok {
|
||||
if path == "" {
|
||||
return
|
||||
return inPlaylist
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(path) {
|
||||
rule["path"] = filepath.Clean(filepath.Join(dir, path))
|
||||
dir := filepath.Dir(referencingPlaylistPath)
|
||||
inPlaylist["path"] = filepath.Clean(filepath.Join(dir, path))
|
||||
}
|
||||
}
|
||||
return inPlaylist
|
||||
case criteria.NotInPlaylist:
|
||||
dir := filepath.Dir(referencingPlaylistPath)
|
||||
notInPlaylist := maps.Clone(rule)
|
||||
if path, ok := rule["path"].(string); ok {
|
||||
if path == "" {
|
||||
return
|
||||
return notInPlaylist
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(path) {
|
||||
rule["path"] = filepath.Clean(filepath.Join(dir, path))
|
||||
dir := filepath.Dir(referencingPlaylistPath)
|
||||
notInPlaylist["path"] = filepath.Clean(filepath.Join(dir, path))
|
||||
}
|
||||
}
|
||||
return notInPlaylist
|
||||
}
|
||||
return
|
||||
|
||||
return inputRule
|
||||
}
|
||||
|
||||
type Playlists []Playlist
|
||||
|
||||
@ -55,6 +55,7 @@ var _ = Describe("Playlist", func() {
|
||||
criteria.InPlaylist{"path": "/test/my-test-path.m3u"},
|
||||
criteria.InPlaylist{"path": "../my-test-path.m3u"},
|
||||
criteria.NotInPlaylist{"path": "/not-test/not-my-test-path.m3u"},
|
||||
criteria.Eq{"artist": "Bob Dealin'"},
|
||||
criteria.Any{
|
||||
criteria.InPlaylist{"path": "../../in-the-test.nsp"},
|
||||
criteria.NotInPlaylist{"path": "./sibling.nsp"},
|
||||
@ -69,12 +70,13 @@ var _ = Describe("Playlist", func() {
|
||||
},
|
||||
Path: "/test/nested/my-playlist.nsp"}
|
||||
|
||||
pls.NormalizeChildPaths()
|
||||
Expect(pls.Rules).Should(BeEquivalentTo(&criteria.Criteria{
|
||||
newPls := pls.WithNormalizeChildPaths()
|
||||
Expect(newPls.Rules).Should(BeEquivalentTo(&criteria.Criteria{
|
||||
Expression: criteria.All{
|
||||
criteria.InPlaylist{"path": "/test/my-test-path.m3u"},
|
||||
criteria.InPlaylist{"path": "/test/my-test-path.m3u"},
|
||||
criteria.NotInPlaylist{"path": "/not-test/not-my-test-path.m3u"},
|
||||
criteria.Eq{"artist": "Bob Dealin'"},
|
||||
criteria.Any{
|
||||
criteria.InPlaylist{"path": "/in-the-test.nsp"},
|
||||
criteria.NotInPlaylist{"path": "/test/nested/sibling.nsp"},
|
||||
@ -98,8 +100,8 @@ var _ = Describe("Playlist", func() {
|
||||
},
|
||||
Path: ""}
|
||||
|
||||
pls.NormalizeChildPaths()
|
||||
Expect(pls.Rules).Should(BeEquivalentTo(&criteria.Criteria{
|
||||
newPls := pls.WithNormalizeChildPaths()
|
||||
Expect(newPls.Rules).Should(BeEquivalentTo(&criteria.Criteria{
|
||||
Expression: criteria.All{
|
||||
criteria.InPlaylist{"path": "../my-test-path.m3u"},
|
||||
},
|
||||
|
||||
@ -31,17 +31,18 @@ func (r *playlistRepository) refreshSmartPlaylist(pls *model.Playlist) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
rulesSQL := newSmartPlaylistCriteria(*pls.Rules, withSmartPlaylistOwner(*usr))
|
||||
normalisedPls := pls.WithNormalizeChildPaths()
|
||||
rulesSQL := newSmartPlaylistCriteria(*normalisedPls.Rules, withSmartPlaylistOwner(*usr))
|
||||
|
||||
if !r.refreshChildPlaylists(pls, rulesSQL) {
|
||||
if !r.refreshChildPlaylists(&normalisedPls, rulesSQL) {
|
||||
return false
|
||||
}
|
||||
|
||||
if err := r.resolvePercentageLimit(pls, &rulesSQL, usr.ID); err != nil {
|
||||
if err := r.resolvePercentageLimit(&normalisedPls, &rulesSQL, usr.ID); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
sq := r.buildSmartPlaylistQuery(pls, rulesSQL, usr.ID)
|
||||
sq := r.buildSmartPlaylistQuery(&normalisedPls, rulesSQL, usr.ID)
|
||||
sq, err := r.addCriteria(sq, rulesSQL)
|
||||
if err != nil {
|
||||
log.Error(r.ctx, "Error building smart playlist criteria", "playlist", pls.Name, "id", pls.ID, err)
|
||||
@ -96,7 +97,6 @@ func (r *playlistRepository) refreshChildPlaylists(pls *model.Playlist, rulesSQL
|
||||
return true
|
||||
}
|
||||
|
||||
pls.NormalizeChildPaths()
|
||||
childPlaylists, err := r.GetAll(model.QueryOptions{Filters: Or{Eq{"playlist.id": childPlaylistIds}, Eq{"playlist.path": childPlaylistPaths}}})
|
||||
if err != nil {
|
||||
log.Error(r.ctx, "Error loading child playlists for smart playlist refresh", "playlist", pls.Name, "id", pls.ID, "childIds", childPlaylistIds, err)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user