musicbrainz-provider #2
@@ -30,7 +30,7 @@ func GetExternalRelease(db *DB, rgid string) (*ExternalRelease, error) {
|
|||||||
func SaveExternalRelease(db *DB, release *ExternalRelease) error {
|
func SaveExternalRelease(db *DB, release *ExternalRelease) error {
|
||||||
var cachedAt interface{}
|
var cachedAt interface{}
|
||||||
if !release.CachedAt.IsZero() {
|
if !release.CachedAt.IsZero() {
|
||||||
cachedAt = release.CachedAt.Format("2006-01-02 15:04:05")
|
cachedAt = release.CachedAt.UTC().Format("2006-01-02 15:04:05")
|
||||||
}
|
}
|
||||||
_, err := db.Conn().Exec(
|
_, err := db.Conn().Exec(
|
||||||
"INSERT OR REPLACE INTO external_releases (rgid, artist_id, title, type, release_date, is_ignored, cached_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
"INSERT OR REPLACE INTO external_releases (rgid, artist_id, title, type, release_date, is_ignored, cached_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||||
@@ -145,7 +145,7 @@ func CountExternalReleases(db *DB) (int, error) {
|
|||||||
// GetExternalReleasesByArtistWithCache returns cached external_release rows for a given artist_id
|
// GetExternalReleasesByArtistWithCache returns cached external_release rows for a given artist_id
|
||||||
// that are within the specified TTL.
|
// that are within the specified TTL.
|
||||||
func GetExternalReleasesByArtistWithCache(db *DB, artistID string, ttl time.Duration) ([]ExternalRelease, error) {
|
func GetExternalReleasesByArtistWithCache(db *DB, artistID string, ttl time.Duration) ([]ExternalRelease, error) {
|
||||||
cutoff := time.Now().Add(-ttl)
|
cutoff := time.Now().UTC().Add(-ttl)
|
||||||
rows, err := db.Conn().Query(
|
rows, err := db.Conn().Query(
|
||||||
"SELECT rgid, artist_id, title, type, release_date, is_ignored, cached_at FROM external_releases WHERE artist_id = ? AND cached_at >= ?",
|
"SELECT rgid, artist_id, title, type, release_date, is_ignored, cached_at FROM external_releases WHERE artist_id = ? AND cached_at >= ?",
|
||||||
artistID, cutoff.Format("2006-01-02 15:04:05"),
|
artistID, cutoff.Format("2006-01-02 15:04:05"),
|
||||||
|
|||||||
@@ -26,6 +26,14 @@ var includedTypes = map[string]bool{
|
|||||||
"Compilation": true,
|
"Compilation": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Precompiled regexes for NormalizeString — compiled once at package init.
|
||||||
|
var (
|
||||||
|
bracketRe = regexp.MustCompile(`\[[^\]]*\]`)
|
||||||
|
parenRe = regexp.MustCompile(`\([^)]*\)`)
|
||||||
|
yearRe = regexp.MustCompile(`\b(1[0-9]{3}|2[0-9]{3})\b`)
|
||||||
|
spaceRe = regexp.MustCompile(`\s+`)
|
||||||
|
)
|
||||||
|
|
||||||
// GetArtistReleaseGroups fetches all release groups for a given artist from MusicBrainz.
|
// GetArtistReleaseGroups fetches all release groups for a given artist from MusicBrainz.
|
||||||
// It queries the artist's release groups via the MusicBrainz Web Service API,
|
// It queries the artist's release groups via the MusicBrainz Web Service API,
|
||||||
// parses the XML response, and applies status and type filtering.
|
// parses the XML response, and applies status and type filtering.
|
||||||
@@ -57,7 +65,9 @@ func (c *MusicBrainzClient) GetArtistReleaseGroups(ctx context.Context, artistMB
|
|||||||
allGroups = append(allGroups, parsed.ReleaseGroups...)
|
allGroups = append(allGroups, parsed.ReleaseGroups...)
|
||||||
|
|
||||||
// If we've fetched all results, we've reached the end.
|
// If we've fetched all results, we've reached the end.
|
||||||
if offset+len(parsed.ReleaseGroups) >= parsed.Count {
|
// Also break on empty page to prevent infinite loop if API
|
||||||
|
// returns fewer items than advertised by count.
|
||||||
|
if len(parsed.ReleaseGroups) == 0 || offset+len(parsed.ReleaseGroups) >= parsed.Count {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,15 +121,12 @@ func NormalizeString(s string) string {
|
|||||||
s = strings.ToLower(s)
|
s = strings.ToLower(s)
|
||||||
|
|
||||||
// Remove bracketed content first (e.g., [Deluxe Edition], [Remastered 2020])
|
// Remove bracketed content first (e.g., [Deluxe Edition], [Remastered 2020])
|
||||||
bracketRe := regexp.MustCompile(`\[[^\]]*\]`)
|
|
||||||
s = bracketRe.ReplaceAllString(s, "")
|
s = bracketRe.ReplaceAllString(s, "")
|
||||||
|
|
||||||
// Remove parenthesized content (e.g., (Deluxe), (Remastered))
|
// Remove parenthesized content (e.g., (Deluxe), (Remastered))
|
||||||
parenRe := regexp.MustCompile(`\([^)]*\)`)
|
|
||||||
s = parenRe.ReplaceAllString(s, "")
|
s = parenRe.ReplaceAllString(s, "")
|
||||||
|
|
||||||
// Remove years (4-digit numbers between 1000-2999)
|
// Remove years (4-digit numbers between 1000-2999)
|
||||||
yearRe := regexp.MustCompile(`\b(1[0-9]{3}|2[0-9]{3})\b`)
|
|
||||||
s = yearRe.ReplaceAllString(s, "")
|
s = yearRe.ReplaceAllString(s, "")
|
||||||
|
|
||||||
// Replace common separators with spaces before stripping other special chars
|
// Replace common separators with spaces before stripping other special chars
|
||||||
@@ -136,7 +143,6 @@ func NormalizeString(s string) string {
|
|||||||
s = b.String()
|
s = b.String()
|
||||||
|
|
||||||
// Collapse multiple spaces
|
// Collapse multiple spaces
|
||||||
spaceRe := regexp.MustCompile(`\s+`)
|
|
||||||
s = spaceRe.ReplaceAllString(s, " ")
|
s = spaceRe.ReplaceAllString(s, " ")
|
||||||
|
|
||||||
// Trim
|
// Trim
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ func SyncArtistDiscography(
|
|||||||
filtered := FilterReleaseGroups(groups)
|
filtered := FilterReleaseGroups(groups)
|
||||||
|
|
||||||
// Step 5: Upsert within a transaction — delete old entries first, then insert new ones.
|
// Step 5: Upsert within a transaction — delete old entries first, then insert new ones.
|
||||||
now := time.Now()
|
now := time.Now().UTC()
|
||||||
tx, err := db.Begin()
|
tx, err := db.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("sync artist discography: begin transaction: %w", err)
|
return nil, fmt.Errorf("sync artist discography: begin transaction: %w", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user