mirror of
https://github.com/navidrome/navidrome.git
synced 2025-07-14 07:31:28 +03:00
Relates to https://github.com/navidrome/navidrome/issues/4183#issuecomment-2952729458 Signed-off-by: Deluan <deluan@navidrome.org>
101 lines
2.9 KiB
Go
101 lines
2.9 KiB
Go
package metadata
|
|
|
|
import (
|
|
"cmp"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/navidrome/navidrome/conf"
|
|
"github.com/navidrome/navidrome/consts"
|
|
"github.com/navidrome/navidrome/model"
|
|
"github.com/navidrome/navidrome/model/id"
|
|
"github.com/navidrome/navidrome/utils"
|
|
"github.com/navidrome/navidrome/utils/slice"
|
|
"github.com/navidrome/navidrome/utils/str"
|
|
)
|
|
|
|
type hashFunc = func(...string) string
|
|
|
|
// getPID returns the persistent ID for a given spec, getting the referenced values from the metadata
|
|
// The spec is a pipe-separated list of fields, where each field is a comma-separated list of attributes
|
|
// Attributes can be either tags or some processed values like folder, albumid, albumartistid, etc.
|
|
// For each field, it gets all its attributes values and concatenates them, then hashes the result.
|
|
// If a field is empty, it is skipped and the function looks for the next field.
|
|
func createGetPID(hash hashFunc) func(mf model.MediaFile, md Metadata, spec string) string {
|
|
var getPID func(mf model.MediaFile, md Metadata, spec string) string
|
|
getAttr := func(mf model.MediaFile, md Metadata, attr string) string {
|
|
attr = strings.TrimSpace(strings.ToLower(attr))
|
|
switch attr {
|
|
case "albumid":
|
|
return getPID(mf, md, conf.Server.PID.Album)
|
|
case "folder":
|
|
return filepath.Dir(mf.Path)
|
|
case "albumartistid":
|
|
return hash(str.Clear(strings.ToLower(mf.AlbumArtist)))
|
|
case "title":
|
|
return mf.Title
|
|
case "album":
|
|
return str.Clear(strings.ToLower(md.String(model.TagAlbum)))
|
|
}
|
|
return md.String(model.TagName(attr))
|
|
}
|
|
getPID = func(mf model.MediaFile, md Metadata, spec string) string {
|
|
pid := ""
|
|
fields := strings.Split(spec, "|")
|
|
for _, field := range fields {
|
|
attributes := strings.Split(field, ",")
|
|
hasValue := false
|
|
values := slice.Map(attributes, func(attr string) string {
|
|
v := getAttr(mf, md, attr)
|
|
if v != "" {
|
|
hasValue = true
|
|
}
|
|
return v
|
|
})
|
|
if hasValue {
|
|
pid += strings.Join(values, "\\")
|
|
break
|
|
}
|
|
}
|
|
return hash(pid)
|
|
}
|
|
|
|
return func(mf model.MediaFile, md Metadata, spec string) string {
|
|
switch spec {
|
|
case "track_legacy":
|
|
return legacyTrackID(mf)
|
|
case "album_legacy":
|
|
return legacyAlbumID(md)
|
|
}
|
|
return getPID(mf, md, spec)
|
|
}
|
|
}
|
|
|
|
func (md Metadata) trackPID(mf model.MediaFile) string {
|
|
return createGetPID(id.NewHash)(mf, md, conf.Server.PID.Track)
|
|
}
|
|
|
|
func (md Metadata) albumID(mf model.MediaFile) string {
|
|
return createGetPID(id.NewHash)(mf, md, conf.Server.PID.Album)
|
|
}
|
|
|
|
// BFR Must be configurable?
|
|
func (md Metadata) artistID(name string) string {
|
|
mf := model.MediaFile{AlbumArtist: name}
|
|
return createGetPID(id.NewHash)(mf, md, "albumartistid")
|
|
}
|
|
|
|
func (md Metadata) mapTrackTitle() string {
|
|
if title := md.String(model.TagTitle); title != "" {
|
|
return title
|
|
}
|
|
return utils.BaseName(md.FilePath())
|
|
}
|
|
|
|
func (md Metadata) mapAlbumName() string {
|
|
return cmp.Or(
|
|
md.String(model.TagAlbum),
|
|
consts.UnknownAlbum,
|
|
)
|
|
}
|