mirror of
https://github.com/navidrome/navidrome.git
synced 2025-07-17 17:02:05 +03:00
107 lines
3.1 KiB
Go
107 lines
3.1 KiB
Go
package metadata
|
|
|
|
import (
|
|
"cmp"
|
|
"fmt"
|
|
"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
|
|
|
|
// createGetPID returns a function that calculates 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.
|
|
type getPIDFunc = func(mf model.MediaFile, md Metadata, spec string, prependLibId bool) string
|
|
|
|
func createGetPID(hash hashFunc) getPIDFunc {
|
|
var getPID getPIDFunc
|
|
getAttr := func(mf model.MediaFile, md Metadata, attr string, prependLibId bool) string {
|
|
attr = strings.TrimSpace(strings.ToLower(attr))
|
|
switch attr {
|
|
case "albumid":
|
|
return getPID(mf, md, conf.Server.PID.Album, prependLibId)
|
|
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, prependLibId bool) 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, prependLibId)
|
|
if v != "" {
|
|
hasValue = true
|
|
}
|
|
return v
|
|
})
|
|
if hasValue {
|
|
pid += strings.Join(values, "\\")
|
|
break
|
|
}
|
|
}
|
|
if prependLibId {
|
|
pid = fmt.Sprintf("%d\\%s", mf.LibraryID, pid)
|
|
}
|
|
return hash(pid)
|
|
}
|
|
|
|
return func(mf model.MediaFile, md Metadata, spec string, prependLibId bool) string {
|
|
switch spec {
|
|
case "track_legacy":
|
|
return legacyTrackID(mf, prependLibId)
|
|
case "album_legacy":
|
|
return legacyAlbumID(mf, md, prependLibId)
|
|
}
|
|
return getPID(mf, md, spec, prependLibId)
|
|
}
|
|
}
|
|
|
|
func (md Metadata) trackPID(mf model.MediaFile) string {
|
|
return createGetPID(id.NewHash)(mf, md, conf.Server.PID.Track, true)
|
|
}
|
|
|
|
func (md Metadata) albumID(mf model.MediaFile, pidConf string) string {
|
|
return createGetPID(id.NewHash)(mf, md, pidConf, true)
|
|
}
|
|
|
|
// BFR Must be configurable?
|
|
func (md Metadata) artistID(name string) string {
|
|
mf := model.MediaFile{AlbumArtist: name}
|
|
return createGetPID(id.NewHash)(mf, md, "albumartistid", false)
|
|
}
|
|
|
|
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,
|
|
)
|
|
}
|