Files
yellowjacket/backend/autotag/groupkey.go
T
2026-05-01 11:52:50 -04:00

48 lines
1.5 KiB
Go

// Package autotag provides the shared primitives used by the
// MusicBrainz autotagger: deterministic album-group keys, scoring,
// and (in later phases) MB orchestration.
package autotag
import (
"crypto/sha1" //nolint:gosec // non-crypto deterministic grouping key.
"encoding/hex"
"path/filepath"
"strconv"
"strings"
)
// GroupKey returns a deterministic album-group identifier for the
// file at filePath belonging to libraryID, carrying the given disc
// number.
//
// The key is a lower-case hex SHA-1 over
//
// libraryID || 0 || normalized_parent_dir || 0 || disc_number
//
// where the parent directory is lower-cased. The folder is taken
// as the album boundary — including the album tag string would
// fragment albums whose tracks carry slightly different tags
// (`Abbey Road` vs `Abbey Road (Remastered 2009)`, etc.). The
// album name is still surfaced in `tagging_items.album_name` for
// the review UI; it just doesn't decide grouping.
//
// Using SHA-1 matches the codebase's existing non-crypto
// deterministic-key convention; collision risk at album-group
// cardinality is irrelevant.
func GroupKey(
libraryID int64,
filePath string,
discNumber int,
) string {
parentDir := strings.ToLower(filepath.Dir(filePath))
h := sha1.New() //nolint:gosec // see package doc — grouping only.
h.Write([]byte(strconv.FormatInt(libraryID, 10)))
h.Write([]byte{0})
h.Write([]byte(parentDir))
h.Write([]byte{0})
h.Write([]byte(strconv.Itoa(discNumber)))
return hex.EncodeToString(h.Sum(nil))
}