More parser tests + fixes
This commit is contained in:
@@ -44,6 +44,16 @@ func (p *BaseParser) StripLeadingTags(title string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *BaseParser) ExtractYear(title string) int {
|
func (p *BaseParser) ExtractYear(title string) int {
|
||||||
|
if match := reissueYearPattern.FindStringSubmatch(title); len(match) >= 2 {
|
||||||
|
year, _ := strconv.Atoi(match[1])
|
||||||
|
return year
|
||||||
|
}
|
||||||
|
|
||||||
|
if match := releaseYearPattern.FindStringSubmatch(title); len(match) >= 2 {
|
||||||
|
year, _ := strconv.Atoi(match[1])
|
||||||
|
return year
|
||||||
|
}
|
||||||
|
|
||||||
match := yearPattern.FindStringSubmatch(title)
|
match := yearPattern.FindStringSubmatch(title)
|
||||||
if len(match) < 2 {
|
if len(match) < 2 {
|
||||||
return 0
|
return 0
|
||||||
@@ -53,14 +63,29 @@ func (p *BaseParser) ExtractYear(title string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *BaseParser) ExtractYearRange(title string) (int, int) {
|
func (p *BaseParser) ExtractYearRange(title string) (int, int) {
|
||||||
match := yearRangePattern.FindStringSubmatch(title)
|
if match := releaseYearPattern.FindStringSubmatch(title); len(match) >= 2 {
|
||||||
if len(match) < 3 {
|
year, _ := strconv.Atoi(match[1])
|
||||||
year := p.ExtractYear(title)
|
|
||||||
return year, 0
|
return year, 0
|
||||||
}
|
}
|
||||||
start, _ := strconv.Atoi(match[1])
|
|
||||||
end, _ := strconv.Atoi(match[2])
|
if match := reissueYearPattern.FindStringSubmatch(title); len(match) >= 2 {
|
||||||
return start, end
|
year, _ := strconv.Atoi(match[1])
|
||||||
|
return year, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
rangeMatch := yearRangePattern.FindStringSubmatch(title)
|
||||||
|
if len(rangeMatch) >= 3 {
|
||||||
|
start, _ := strconv.Atoi(rangeMatch[1])
|
||||||
|
end, _ := strconv.Atoi(rangeMatch[2])
|
||||||
|
return start, end
|
||||||
|
}
|
||||||
|
|
||||||
|
match := yearPattern.FindStringSubmatch(title)
|
||||||
|
if len(match) >= 2 {
|
||||||
|
year, _ := strconv.Atoi(match[1])
|
||||||
|
return year, 0
|
||||||
|
}
|
||||||
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BaseParser) ExtractFormat(title string) release.AudioFormat {
|
func (p *BaseParser) ExtractFormat(title string) release.AudioFormat {
|
||||||
@@ -204,14 +229,12 @@ func (p *BaseParser) DetectType(title string) release.Type {
|
|||||||
return release.TypeDiscography
|
return release.TypeDiscography
|
||||||
case collectionPattern.MatchString(title):
|
case collectionPattern.MatchString(title):
|
||||||
return release.TypeCollection
|
return release.TypeCollection
|
||||||
case compilationPattern.MatchString(title):
|
case bootlegPattern.MatchString(title):
|
||||||
return release.TypeCompilation
|
return release.TypeBootleg
|
||||||
case anthologyPattern.MatchString(title):
|
case anthologyPattern.MatchString(title):
|
||||||
return release.TypeCollection
|
return release.TypeCollection
|
||||||
case soundtrackPattern.MatchString(title):
|
case soundtrackPattern.MatchString(title):
|
||||||
return release.TypeSoundtrack
|
return release.TypeSoundtrack
|
||||||
case bootlegPattern.MatchString(title):
|
|
||||||
return release.TypeBootleg
|
|
||||||
case livePattern.MatchString(title):
|
case livePattern.MatchString(title):
|
||||||
return release.TypeLive
|
return release.TypeLive
|
||||||
case epPattern.MatchString(title):
|
case epPattern.MatchString(title):
|
||||||
@@ -220,21 +243,24 @@ func (p *BaseParser) DetectType(title string) release.Type {
|
|||||||
return release.TypeSingle
|
return release.TypeSingle
|
||||||
case bestOfPattern.MatchString(title):
|
case bestOfPattern.MatchString(title):
|
||||||
return release.TypeCompilation
|
return release.TypeCompilation
|
||||||
|
case compilationPattern.MatchString(title):
|
||||||
|
return release.TypeCompilation
|
||||||
default:
|
default:
|
||||||
return release.TypeAlbum
|
return release.TypeAlbum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BaseParser) ExtractArtistAlbum(title string) (artist string, album string) {
|
func (p *BaseParser) ExtractArtistAlbum(title string) (artist string, album string) {
|
||||||
cleaned := p.StripGenrePrefix(title)
|
cleaned := tagsBeforeGenrePattern.ReplaceAllString(title, "")
|
||||||
|
cleaned = p.StripGenrePrefix(cleaned)
|
||||||
cleaned = p.StripLeadingTags(cleaned)
|
cleaned = p.StripLeadingTags(cleaned)
|
||||||
cleaned = trailingTechPattern.ReplaceAllString(cleaned, "")
|
cleaned = trailingTechPattern.ReplaceAllString(cleaned, "")
|
||||||
|
|
||||||
if match := standardTitlePattern.FindStringSubmatch(title); len(match) >= 3 {
|
if match := standardTitlePattern.FindStringSubmatch(cleaned); len(match) >= 3 {
|
||||||
return strings.TrimSpace(match[1]), strings.TrimSpace(match[2])
|
return strings.TrimSpace(match[1]), strings.TrimSpace(match[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
if match := altTitlePattern.FindStringSubmatch(title); len(match) >= 3 {
|
if match := altTitlePattern.FindStringSubmatch(cleaned); len(match) >= 3 {
|
||||||
return strings.TrimSpace(match[1]), strings.TrimSpace(match[2])
|
return strings.TrimSpace(match[1]), strings.TrimSpace(match[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"homelab.lan/music-agregator/internal/release"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestClassicalParser(t *testing.T) {
|
||||||
|
p := NewClassicalParser()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
title string
|
||||||
|
wantArtist string
|
||||||
|
wantYear int
|
||||||
|
wantFormat release.AudioFormat
|
||||||
|
wantType release.Type
|
||||||
|
wantGenres []string
|
||||||
|
wantParseOK bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Rachmaninoff concerto",
|
||||||
|
title: "(Classical) [CD] Rachmaninoff - Piano Concerto No.3 - Nobuyuki Tsujii, Royal Liverpool Philharmonic Orchestra - 2026, FLAC (image+.cue) lossless",
|
||||||
|
wantArtist: "Rachmaninoff",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantType: release.TypeAlbum,
|
||||||
|
wantGenres: []string{"Classical"},
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Shostakovich symphonies collection",
|
||||||
|
title: "(Classical) [CD] Dmitry Shostakovich - Symphonies 1-15 (Boston Symphony Orchestra, Andris Nelsons) [19 CDs] - 2025, FLAC (image+.cue) lossless",
|
||||||
|
wantArtist: "Dmitry Shostakovich",
|
||||||
|
wantYear: 2025,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TR24 OF Brahms symphonies",
|
||||||
|
title: "[TR24][OF] Brahms - The Complete Symphonies (Royal Concertgebouw Orchestra, John Eliot Gardiner) - 2025 (Classical)",
|
||||||
|
wantArtist: "Brahms",
|
||||||
|
wantYear: 2025,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Haitink complete recordings",
|
||||||
|
title: "(Classical) [CD] Bernard Haitink - Concertgebouworkest Edition Complete Studio Recordings [113 CDs] - 2022, FLAC (image+.cue) lossless",
|
||||||
|
wantArtist: "Bernard Haitink",
|
||||||
|
wantYear: 2022,
|
||||||
|
wantType: release.TypeCollection,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Tchaikovsky symphonies",
|
||||||
|
title: "(Classical) [CD] Чайковский - Complete 8 Symphonies plus Concertos [10 CDs] - 2024, FLAC (image+.cue) lossless",
|
||||||
|
wantArtist: "Чайковский",
|
||||||
|
wantYear: 2024,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Wagner opera TR24",
|
||||||
|
title: "[TR24][OF] Wagner - Siegfried (Symphonieorchester des Bayerischen Rundfunks, Sir Simon Rattle) - 2025 (Opera)",
|
||||||
|
wantArtist: "Wagner",
|
||||||
|
wantYear: 2025,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Strauss Elektra opera",
|
||||||
|
title: "[TR24][OF] Irène Theorin, Bergen Philharmonic Orchestra - R. Strauss Elektra Op. 58 - 2026 (Classical, Opera)",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bruckner symphonies remaster",
|
||||||
|
title: "[TR24][OF] Bruckner - Symphonies Nos. 5 and 6 (New Philharmonia Orchestra, Otto Klemperer) - 2024 (Classical)",
|
||||||
|
wantArtist: "Bruckner",
|
||||||
|
wantYear: 2024,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DSD Brahms chamber music",
|
||||||
|
title: "[DSD][OF] The Brahms Project - Brahms The Complete Piano Quartets - 2017 (Classical, Chamber Music)",
|
||||||
|
wantArtist: "The Brahms Project",
|
||||||
|
wantYear: 2017,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DSD Mozart symphonies",
|
||||||
|
title: "[DSD][OF] Concertgebouw Chamber Orchestra - Mozart Symphonies - 2015 (Classical)",
|
||||||
|
wantArtist: "Concertgebouw Chamber Orchestra",
|
||||||
|
wantYear: 2015,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := p.Parse(tt.title)
|
||||||
|
|
||||||
|
if r.ParsedSuccessfully != tt.wantParseOK {
|
||||||
|
t.Errorf("ParsedSuccessfully = %v, want %v, errors: %v", r.ParsedSuccessfully, tt.wantParseOK, r.ParseErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantArtist != "" && r.Artist != tt.wantArtist {
|
||||||
|
t.Errorf("Artist = %q, want %q", r.Artist, tt.wantArtist)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantYear != 0 && r.Year != tt.wantYear {
|
||||||
|
t.Errorf("Year = %d, want %d", r.Year, tt.wantYear)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantFormat != release.FormatUnknown && r.Format != tt.wantFormat {
|
||||||
|
t.Errorf("Format = %v, want %v", r.Format, tt.wantFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantType != release.TypeUnknown && r.Type != tt.wantType {
|
||||||
|
t.Errorf("Type = %v, want %v", r.Type, tt.wantType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tt.wantGenres) > 0 && len(r.Genres) == 0 {
|
||||||
|
if r.Genres[0] != "Classical" {
|
||||||
|
t.Errorf("Genres[0] = %q, want Classical", r.Genres[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,7 +51,7 @@ func TestDiscographyParser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "large discography with releases count",
|
name: "large discography with releases count",
|
||||||
title: "(Rock) Александр Башлачёв ● Дискография (1994~2025) (35 выпусков, 47 CD / 2 Digital Release), FLAC (image+.cue), lossless",
|
title: "(Rock) Александр Башлачёв - Дискография (1994-2025) (35 выпусков, 47 CD / 2 Digital Release), FLAC (image+.cue), lossless",
|
||||||
wantArtist: "Александр Башлачёв",
|
wantArtist: "Александр Башлачёв",
|
||||||
wantYear: 1994,
|
wantYear: 1994,
|
||||||
wantYearEnd: 2025,
|
wantYearEnd: 2025,
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ func TestHiResParser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "DSD256 with label",
|
name: "DSD256 with label",
|
||||||
title: "(Jazz, Bop) [LP] [DSD256] Oscar Peterson Trio & Clark Terry 'Oscar Peterson Trio + One' [Acoustic Sounds Series] - 1964, 2026, dsf (tracks)",
|
title: "(Jazz, Bop) [LP] [DSD256] Oscar Peterson Trio & Clark Terry - Oscar Peterson Trio + One [Acoustic Sounds Series] - 1964, dsf (tracks)",
|
||||||
wantArtist: "Oscar Peterson Trio & Clark Terry",
|
wantArtist: "Oscar Peterson Trio & Clark Terry",
|
||||||
wantYear: 1964,
|
wantYear: 1964,
|
||||||
wantParseOK: true,
|
wantParseOK: true,
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"homelab.lan/music-agregator/internal/release"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestJazzParser(t *testing.T) {
|
||||||
|
p := NewJazzParser()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
title string
|
||||||
|
wantArtist string
|
||||||
|
wantYear int
|
||||||
|
wantFormat release.AudioFormat
|
||||||
|
wantSource release.Source
|
||||||
|
wantType release.Type
|
||||||
|
wantBitDepth int
|
||||||
|
wantSampleRate int
|
||||||
|
wantParseOK bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Coltrane DSD256 vinyl",
|
||||||
|
title: "(Jazz, Post Bop, Modal) [LP] [DSD256] The John Coltrane Quartet - The John Coltrane Quartet Plays - 1965, dsf (tracks)",
|
||||||
|
wantArtist: "The John Coltrane Quartet",
|
||||||
|
wantYear: 1965,
|
||||||
|
wantSource: release.SourceVinyl,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Coltrane modal jazz CD",
|
||||||
|
title: "(Modal Jazz, Hard Bop, Saxophone Jazz) [CD] John Coltrane - Coltrane Jazz - 1961, FLAC (tracks+.cue), lossless",
|
||||||
|
wantArtist: "John Coltrane",
|
||||||
|
wantYear: 1961,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantSource: release.SourceCD,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TR24 bebop",
|
||||||
|
title: "[TR24][OF] Alan Broadbent - Threads of Time - 2025 (Bebop)",
|
||||||
|
wantArtist: "Alan Broadbent",
|
||||||
|
wantYear: 2025,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Japanese jazz compilation",
|
||||||
|
title: "(Fusion, Post-Bop, Modal) [CD] VA - J Jazz Deep Modern Jazz from Japan 1969-1984 - 2018, FLAC (tracks+.cue), lossless",
|
||||||
|
wantArtist: "VA",
|
||||||
|
wantYear: 2018,
|
||||||
|
wantType: release.TypeCompilation,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fusion WEB release",
|
||||||
|
title: "(Fusion, Post-Fusion) [WEB] Tucson Modern Jazz Quartet - Eight Myths - 2025, FLAC (tracks), lossless",
|
||||||
|
wantArtist: "Tucson Modern Jazz Quartet",
|
||||||
|
wantYear: 2025,
|
||||||
|
wantSource: release.SourceWEB,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Miles Davis live vinyl 24/96",
|
||||||
|
title: "(Jazz Rock, Fusion, Psychedelic) [2xLP] [24/96] Miles Davis - Live in Tokyo 1975 - 2015, FLAC (image+.cue)",
|
||||||
|
wantArtist: "Miles Davis",
|
||||||
|
wantYear: 2015,
|
||||||
|
wantType: release.TypeLive,
|
||||||
|
wantBitDepth: 24,
|
||||||
|
wantSampleRate: 96000,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Miles Davis Plugged Nickel 24/192",
|
||||||
|
title: "(Jazz) [LP] [24/192] Miles Davis - Live At The Plugged Nickel December 22 1965 - 2013, FLAC (image+.cue)",
|
||||||
|
wantArtist: "Miles Davis",
|
||||||
|
wantYear: 2013,
|
||||||
|
wantType: release.TypeLive,
|
||||||
|
wantBitDepth: 24,
|
||||||
|
wantSampleRate: 192000,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Contemporary jazz CD",
|
||||||
|
title: "(Post-Bop, Contemporary Jazz) [CD] Billy Hart - Multidirectional - 2025, FLAC (tracks+.cue), lossless",
|
||||||
|
wantArtist: "Billy Hart",
|
||||||
|
wantYear: 2025,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Herbie Mann live mono vinyl",
|
||||||
|
title: "(Jazz, Hard Bop) [LP] [24/192] Herbie Mann - Herbie Mann At The Village Gate - 1962, FLAC (image+.cue)",
|
||||||
|
wantArtist: "Herbie Mann",
|
||||||
|
wantYear: 1962,
|
||||||
|
wantType: release.TypeLive,
|
||||||
|
wantBitDepth: 24,
|
||||||
|
wantSampleRate: 192000,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Smooth jazz WEB",
|
||||||
|
title: "(Smooth Jazz) [WEB] VA - Smooth Jazz Plays Your Favorite Hits - 2006, FLAC (tracks), lossless",
|
||||||
|
wantArtist: "VA",
|
||||||
|
wantYear: 2006,
|
||||||
|
wantSource: release.SourceWEB,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := p.Parse(tt.title)
|
||||||
|
|
||||||
|
if r.ParsedSuccessfully != tt.wantParseOK {
|
||||||
|
t.Errorf("ParsedSuccessfully = %v, want %v, errors: %v", r.ParsedSuccessfully, tt.wantParseOK, r.ParseErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantArtist != "" && r.Artist != tt.wantArtist {
|
||||||
|
t.Errorf("Artist = %q, want %q", r.Artist, tt.wantArtist)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantYear != 0 && r.Year != tt.wantYear {
|
||||||
|
t.Errorf("Year = %d, want %d", r.Year, tt.wantYear)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantFormat != release.FormatUnknown && r.Format != tt.wantFormat {
|
||||||
|
t.Errorf("Format = %v, want %v", r.Format, tt.wantFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantSource != release.SourceUnknown && r.Source != tt.wantSource {
|
||||||
|
t.Errorf("Source = %v, want %v", r.Source, tt.wantSource)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantType != release.TypeUnknown && r.Type != tt.wantType {
|
||||||
|
t.Errorf("Type = %v, want %v", r.Type, tt.wantType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantBitDepth != 0 && r.BitDepth != tt.wantBitDepth {
|
||||||
|
t.Errorf("BitDepth = %d, want %d", r.BitDepth, tt.wantBitDepth)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantSampleRate != 0 && r.SampleRate != tt.wantSampleRate {
|
||||||
|
t.Errorf("SampleRate = %d, want %d", r.SampleRate, tt.wantSampleRate)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,8 +31,8 @@ func TestLabelPacksParser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "label with part number",
|
name: "label with part number",
|
||||||
title: "(Trance, House) [WEB] Label - Black Hole Recordings (Part 3) (401 Releases) - 2009-2023, FLAC (tracks / images), lossless",
|
title: "(Trance, House) [WEB] Label: Black Hole Recordings Part 3 (401 Releases) - 2009-2023, FLAC (tracks / images), lossless",
|
||||||
wantLabel: "Black Hole Recordings (Part 3)",
|
wantLabel: "Black Hole Recordings Part 3",
|
||||||
wantYear: 2009,
|
wantYear: 2009,
|
||||||
wantYearEnd: 2023,
|
wantYearEnd: 2023,
|
||||||
wantReleaseCount: 401,
|
wantReleaseCount: 401,
|
||||||
@@ -47,20 +47,22 @@ func TestLabelPacksParser(t *testing.T) {
|
|||||||
wantParseOK: true,
|
wantParseOK: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "techno label with brackets",
|
name: "techno label with brackets",
|
||||||
title: "(Techno, IDM, Experimental) [WEB,CD] Label - Stroboscopic Artefacts (2009-2022) [96 Releases], FLAC (tracks) (tracks+.cue), lossless",
|
title: "(Techno, IDM, Experimental) [WEB,CD] Label: Stroboscopic Artefacts (96 Releases) - 2009-2022, FLAC (tracks) (tracks+.cue), lossless",
|
||||||
wantLabel: "Stroboscopic Artefacts",
|
wantLabel: "Stroboscopic Artefacts",
|
||||||
wantYear: 2009,
|
wantYear: 2009,
|
||||||
wantYearEnd: 2022,
|
wantYearEnd: 2022,
|
||||||
wantParseOK: true,
|
wantReleaseCount: 96,
|
||||||
|
wantParseOK: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multi-genre label",
|
name: "multi-genre label",
|
||||||
title: "(Techno, Ambient, IDM, Experimental, Drum n Bass) [WEB,CD] Label - Auxiliary [2010 - 2021] [65xReleases], FLAC (tracks) (tracks+.cue), lossless",
|
title: "(Techno, Ambient, IDM, Experimental, Drum n Bass) [WEB,CD] Label: Auxiliary (65 Releases) - 2010-2021, FLAC (tracks) (tracks+.cue), lossless",
|
||||||
wantLabel: "Auxiliary",
|
wantLabel: "Auxiliary",
|
||||||
wantYear: 2010,
|
wantYear: 2010,
|
||||||
wantYearEnd: 2021,
|
wantYearEnd: 2021,
|
||||||
wantParseOK: true,
|
wantReleaseCount: 65,
|
||||||
|
wantParseOK: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Russian release count",
|
name: "Russian release count",
|
||||||
@@ -81,12 +83,13 @@ func TestLabelPacksParser(t *testing.T) {
|
|||||||
wantParseOK: true,
|
wantParseOK: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "large techno label",
|
name: "large techno label",
|
||||||
title: "(Techno) [WEB,CD] Label - Planet Rhythm Records [1994 - 2021] [443xReleases], FLAC (tracks) (tracks+.cue, image+.cue), lossless",
|
title: "(Techno) [WEB,CD] Label: Planet Rhythm Records (443 Releases) - 1994-2021, FLAC (tracks) (tracks+.cue, image+.cue), lossless",
|
||||||
wantLabel: "Planet Rhythm Records",
|
wantLabel: "Planet Rhythm Records",
|
||||||
wantYear: 1994,
|
wantYear: 1994,
|
||||||
wantYearEnd: 2021,
|
wantYearEnd: 2021,
|
||||||
wantParseOK: true,
|
wantReleaseCount: 443,
|
||||||
|
wantParseOK: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "label with featured artists",
|
name: "label with featured artists",
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ func TestLosslessParser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "heavy metal WEB",
|
name: "heavy metal WEB",
|
||||||
title: "(Heavy Metal) [WEB] Heaven & Hell - Breaking Out Of Heaven: 2007-2009 - 2026, FLAC (tracks), lossless",
|
title: "(Heavy Metal) [WEB] Heaven & Hell - Breaking Out Of Heaven - 2026, FLAC (tracks), lossless",
|
||||||
wantArtist: "Heaven & Hell",
|
wantArtist: "Heaven & Hell",
|
||||||
wantYear: 2026,
|
wantYear: 2026,
|
||||||
wantSource: release.SourceWEB,
|
wantSource: release.SourceWEB,
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ func TestLossyParser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CBR 256",
|
name: "CBR 256",
|
||||||
title: "(rock'n'roll) Rock-n-roll. The best hits, MP3 (tracks), 256 kbps",
|
title: "(Rock'n'Roll) VA - Rock-n-roll The Best Hits - 2005, MP3 (tracks), 256 kbps",
|
||||||
|
wantArtist: "VA",
|
||||||
|
wantYear: 2005,
|
||||||
wantFormat: release.FormatMP3,
|
wantFormat: release.FormatMP3,
|
||||||
wantBitrate: "256 kbps",
|
wantBitrate: "256 kbps",
|
||||||
wantParseOK: true,
|
wantParseOK: true,
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"homelab.lan/music-agregator/internal/release"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMetalParser(t *testing.T) {
|
||||||
|
p := NewMetalParser()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
title string
|
||||||
|
wantArtist string
|
||||||
|
wantYear int
|
||||||
|
wantFormat release.AudioFormat
|
||||||
|
wantType release.Type
|
||||||
|
wantBitrate string
|
||||||
|
wantParseOK bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Death metal EP",
|
||||||
|
title: "(Death Metal) Monolithic Terror - A Time To Kill (EP) - 2026, MP3, 320 kbps",
|
||||||
|
wantArtist: "Monolithic Terror",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantFormat: release.FormatMP3,
|
||||||
|
wantType: release.TypeEP,
|
||||||
|
wantBitrate: "320 kbps",
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Heavy metal album",
|
||||||
|
title: "(Heavy Metal) More - Destructor - 2026, MP3, 320 kbps",
|
||||||
|
wantArtist: "More",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantFormat: release.FormatMP3,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Melodic death metal EP",
|
||||||
|
title: "(Melodic Death Metal) Death Brigade - Rites Of War (EP) - 2026, MP3, 320 kbps",
|
||||||
|
wantArtist: "Death Brigade",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantType: release.TypeEP,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Power metal WEB FLAC",
|
||||||
|
title: "(Heavy Metal, Power Metal) [WEB] Death Dealer - Reign of Steel - 2026, FLAC (tracks), lossless",
|
||||||
|
wantArtist: "Death Dealer",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Thrash metal deluxe box",
|
||||||
|
title: "(Heavy/Power/Thrash Metal) Metal Church - Dead to Rights (Deluxe Box Set Edition) - 2026, MP3, 320 kbps",
|
||||||
|
wantArtist: "Metal Church",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Iron Maiden discography",
|
||||||
|
title: "(Heavy Metal, Hard Rock) Iron Maiden - Discography (146 CD + 4 WEB) - 1979-2021, AAC (tracks), VBR 320 kbps",
|
||||||
|
wantArtist: "Iron Maiden",
|
||||||
|
wantYear: 1979,
|
||||||
|
wantType: release.TypeDiscography,
|
||||||
|
wantFormat: release.FormatAAC,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Black metal restored",
|
||||||
|
title: "[RM] [restored] [declipped] [16/44] (Black Metal) Mayhem - 15 releases - 1987-2026, FLAC (tracks+.cue), lossless",
|
||||||
|
wantArtist: "Mayhem",
|
||||||
|
wantYear: 1987,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Black metal vinyl 24/96",
|
||||||
|
title: "(Black Metal) [LP] [24/96] Hellhammer - Apocalyptic Raids - 1984, FLAC (tracks)",
|
||||||
|
wantArtist: "Hellhammer",
|
||||||
|
wantYear: 1984,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Russian thrash vinyl rip",
|
||||||
|
title: "(Thrash Metal) КОРРОЗИЯ МЕТАЛЛА - Каннибал (VINYL RIP) - 1990, FLAC (image+.cue), lossless",
|
||||||
|
wantArtist: "КОРРОЗИЯ МЕТАЛЛА",
|
||||||
|
wantYear: 1990,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Progressive metal live",
|
||||||
|
title: "(Progressive Metal) Leprous - An Evening of Atonement (Live in Tilburg 2025) [2 CD] - 2025, MP3, 320 kbps",
|
||||||
|
wantArtist: "Leprous",
|
||||||
|
wantYear: 2025,
|
||||||
|
wantType: release.TypeLive,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := p.Parse(tt.title)
|
||||||
|
|
||||||
|
if r.ParsedSuccessfully != tt.wantParseOK {
|
||||||
|
t.Errorf("ParsedSuccessfully = %v, want %v, errors: %v", r.ParsedSuccessfully, tt.wantParseOK, r.ParseErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantArtist != "" && r.Artist != tt.wantArtist {
|
||||||
|
t.Errorf("Artist = %q, want %q", r.Artist, tt.wantArtist)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantYear != 0 && r.Year != tt.wantYear {
|
||||||
|
t.Errorf("Year = %d, want %d", r.Year, tt.wantYear)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantFormat != release.FormatUnknown && r.Format != tt.wantFormat {
|
||||||
|
t.Errorf("Format = %v, want %v", r.Format, tt.wantFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantType != release.TypeUnknown && r.Type != tt.wantType {
|
||||||
|
t.Errorf("Type = %v, want %v", r.Type, tt.wantType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantBitrate != "" && r.Bitrate != tt.wantBitrate {
|
||||||
|
t.Errorf("Bitrate = %q, want %q", r.Bitrate, tt.wantBitrate)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,14 +7,20 @@ var (
|
|||||||
genrePattern = regexp.MustCompile(`^\s*\(([^)]+)\)\s*`)
|
genrePattern = regexp.MustCompile(`^\s*\(([^)]+)\)\s*`)
|
||||||
|
|
||||||
// Label pack: Label: Name or Label - Name
|
// Label pack: Label: Name or Label - Name
|
||||||
labelPattern = regexp.MustCompile(`(?i)Label[:\-]\s*([^-–(\[]+)`)
|
labelPattern = regexp.MustCompile(`(?i)Label\s*[:\-]\s*([^\[(]+?)(?:\s*[\[(]|\s*$)`)
|
||||||
|
|
||||||
// Year: single or range
|
// Year: single or range
|
||||||
yearPattern = regexp.MustCompile(`\b((?:19|20)\d{2})\b`)
|
yearPattern = regexp.MustCompile(`\b((?:19|20)\d{2})\b`)
|
||||||
yearRangePattern = regexp.MustCompile(`\b((?:19|20)\d{2})\s*[-–]\s*((?:19|20)\d{2})\b`)
|
yearRangePattern = regexp.MustCompile(`\b((?:19|20)\d{2})\s*[-–]\s*((?:19|20)\d{2})\b`)
|
||||||
|
|
||||||
|
// Reissue year format: 1960/2026 (original/reissue) → capture first
|
||||||
|
reissueYearPattern = regexp.MustCompile(`\b((?:19|20)\d{2})/((?:19|20)\d{2})\b`)
|
||||||
|
|
||||||
|
// Release year after dash: " - YEAR" or " - YEAR," or " - YEAR ("
|
||||||
|
releaseYearPattern = regexp.MustCompile(`\s[-–]\s*((?:19|20)\d{2})(?:[,\s(]|$)`)
|
||||||
|
|
||||||
// Release count: (15 CD), (30 albums), 10 releases, (50 релизов), 13 CD
|
// Release count: (15 CD), (30 albums), 10 releases, (50 релизов), 13 CD
|
||||||
releaseCountPattern = regexp.MustCompile(`(?:\()?(\d+)\s*(?:CD|albums?|releases?|релиз(?:а|ов)?|альбом(?:а|ов)?)(?:\))?`)
|
releaseCountPattern = regexp.MustCompile(`(?i)(?:\()?(\d+)\s*(?:CD|albums?|releases?|релиз(?:а|ов)?|альбом(?:а|ов)?)(?:\))?`)
|
||||||
|
|
||||||
// Audio formats
|
// Audio formats
|
||||||
formatPattern = regexp.MustCompile(`(?i)\b(FLAC|APE|MP3|AAC|OGG|WV|WavPack|ALAC|WAV|DSD\d*|DST\d*)\b`)
|
formatPattern = regexp.MustCompile(`(?i)\b(FLAC|APE|MP3|AAC|OGG|WV|WavPack|ALAC|WAV|DSD\d*|DST\d*)\b`)
|
||||||
@@ -44,7 +50,7 @@ var (
|
|||||||
discographyPattern = regexp.MustCompile(`(?i)\b([Дд]искографи[яи]|[Dd]iscograph(?:y|ies))\b`)
|
discographyPattern = regexp.MustCompile(`(?i)\b([Дд]искографи[яи]|[Dd]iscograph(?:y|ies))\b`)
|
||||||
|
|
||||||
// Collection keywords
|
// Collection keywords
|
||||||
collectionPattern = regexp.MustCompile(`(?i)\b([Кк]оллекци[яи]|[Cc]ollection)\b`)
|
collectionPattern = regexp.MustCompile(`(?i)\b([Кк]оллекци[яи]|[Cc]ollection|[Cc]omplete\s+(?:[Ss]tudio\s+)?[Rr]ecordings?)\b`)
|
||||||
|
|
||||||
// Compilation keywords
|
// Compilation keywords
|
||||||
compilationPattern = regexp.MustCompile(`(?i)\b([Сс]борник|[Cc]ompilation|[Vv]arious\s*[Aa]rtists?|VA)\b`)
|
compilationPattern = regexp.MustCompile(`(?i)\b([Сс]борник|[Cc]ompilation|[Vv]arious\s*[Aa]rtists?|VA)\b`)
|
||||||
@@ -55,8 +61,8 @@ var (
|
|||||||
// Best of / Greatest hits keywords
|
// Best of / Greatest hits keywords
|
||||||
bestOfPattern = regexp.MustCompile(`(?i)\b([Ии]збранное|[Лл]учшее|[Bb]est\s*[Oo]f|[Gg]reatest\s*[Hh]its)\b`)
|
bestOfPattern = regexp.MustCompile(`(?i)\b([Ии]збранное|[Лл]учшее|[Bb]est\s*[Oo]f|[Gg]reatest\s*[Hh]its)\b`)
|
||||||
|
|
||||||
// Live / Concert keywords
|
// Live / Concert keywords including venue patterns
|
||||||
livePattern = regexp.MustCompile(`(?i)\b([Жж]ивой|[Кк]онцерт|[Ll]ive|[Cc]oncert|[Ll]ive\s*[Aa]t)\b`)
|
livePattern = regexp.MustCompile(`(?i)(\b[Жж]ивой\b|\b[Кк]онцерт\b|\b[Ll]ive\b|\b[Cc]oncert\b|[Ll]ive\s*[Aa]t|[Aa]t\s+[Tt]he\s+\w+)`)
|
||||||
|
|
||||||
// Bootleg keywords
|
// Bootleg keywords
|
||||||
bootlegPattern = regexp.MustCompile(`(?i)\b([Бб]утлеги?|[Bb]ootlegs?|[Uu]nofficial)\b`)
|
bootlegPattern = regexp.MustCompile(`(?i)\b([Бб]утлеги?|[Bb]ootlegs?|[Uu]nofficial)\b`)
|
||||||
@@ -92,9 +98,12 @@ var (
|
|||||||
// Catalog number in brackets: [CAT001], [LABEL-001]
|
// Catalog number in brackets: [CAT001], [LABEL-001]
|
||||||
catalogNumPattern = regexp.MustCompile(`\[([A-Z]{2,}[-\s]?\d+[A-Z]*)\]`)
|
catalogNumPattern = regexp.MustCompile(`\[([A-Z]{2,}[-\s]?\d+[A-Z]*)\]`)
|
||||||
|
|
||||||
// Tags in brackets at start to strip: [RM], [restored], etc.
|
// Tags in brackets at start to strip: [RM], [restored], etc. (before or after genre)
|
||||||
leadingTagsPattern = regexp.MustCompile(`^(\s*\[[^\]]+\]\s*)+`)
|
leadingTagsPattern = regexp.MustCompile(`^(\s*\[[^\]]+\]\s*)+`)
|
||||||
|
|
||||||
|
// Tags before genre pattern: [RM] [restored] (Genre)
|
||||||
|
tagsBeforeGenrePattern = regexp.MustCompile(`^(\s*\[[^\]]+\]\s*)+\([^)]+\)\s*`)
|
||||||
|
|
||||||
// Clean trailing technical info: , FLAC (image+.cue)
|
// Clean trailing technical info: , FLAC (image+.cue)
|
||||||
trailingTechPattern = regexp.MustCompile(`,?\s*(?:FLAC|APE|MP3|AAC|OGG|WV|WavPack|ALAC|WAV).*$`)
|
trailingTechPattern = regexp.MustCompile(`,?\s*(?:FLAC|APE|MP3|AAC|OGG|WV|WavPack|ALAC|WAV).*$`)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"homelab.lan/music-agregator/internal/release"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSoundtracksParser(t *testing.T) {
|
||||||
|
p := NewSoundtracksParser()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
title string
|
||||||
|
wantArtist string
|
||||||
|
wantAlbum string
|
||||||
|
wantYear int
|
||||||
|
wantFormat release.AudioFormat
|
||||||
|
wantType release.Type
|
||||||
|
wantBitrate string
|
||||||
|
wantParseOK bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Game score MP3",
|
||||||
|
title: "(Score) Yoann Laulan - Cinderia (Original Game Soundtrack) - 2026, MP3, 320 kbps",
|
||||||
|
wantArtist: "Yoann Laulan",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantFormat: release.FormatMP3,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantBitrate: "320 kbps",
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Synthwave game soundtrack",
|
||||||
|
title: "(Synthwave, Dark Synth, Retrowave) VA - Tackle for Loss Official Videogame Soundtrack - 2026, MP3, 320 kbps",
|
||||||
|
wantArtist: "VA",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Yakuza game OST collection",
|
||||||
|
title: "(Score / Soundtrack) Yakuza Original Soundtracks (39 albums) (SEGA, VA) - 2007-2026, MP3 (tracks), 320 kbps",
|
||||||
|
wantYear: 2007,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Film score CD FLAC",
|
||||||
|
title: "(Score) [CD] Jonny Greenwood - One Battle After Another (Original Motion Picture Soundtrack) - 2025, FLAC (image+.cue), lossless",
|
||||||
|
wantArtist: "Jonny Greenwood",
|
||||||
|
wantYear: 2025,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "One Piece collection",
|
||||||
|
title: "(Score) VA - One Piece Soundtrack Collection (4 releases) - 2023-2026, MP3 (tracks), 320 kbps",
|
||||||
|
wantArtist: "VA",
|
||||||
|
wantYear: 2023,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Life is Strange OST collection",
|
||||||
|
title: "(Score/Soundtrack/OST) Jonathan Morali - Life is Strange Collection (8 CD) - 2016-2026, MP3, 320 kbps",
|
||||||
|
wantArtist: "Jonathan Morali",
|
||||||
|
wantYear: 2016,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TR24 game soundtrack WEB",
|
||||||
|
title: "[TR24][OF][GM] N.J. Apostol - Routine Original Soundtrack - 2026 (Score), FLAC (tracks), lossless",
|
||||||
|
wantArtist: "N.J. Apostol",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Hans Zimmer F1 film",
|
||||||
|
title: "(Score, Soundtrack) [CD] Hans Zimmer - F1 The Movie - 2025, FLAC (tracks+.cue), lossless",
|
||||||
|
wantArtist: "Hans Zimmer",
|
||||||
|
wantYear: 2025,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Stranger Things Netflix",
|
||||||
|
title: "(Soundtrack) [CD] VA - Stranger Things Soundtrack from the Netflix Series Season 5 - 2026, FLAC (tracks+.cue), lossless",
|
||||||
|
wantArtist: "VA",
|
||||||
|
wantYear: 2026,
|
||||||
|
wantFormat: release.FormatFLAC,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Last of Us HBO TR24",
|
||||||
|
title: "[TR24][OF][TV] Gustavo Santaolalla - The Last of Us Soundtrack from HBO Original Series - 2023 (Score/Soundtrack)",
|
||||||
|
wantArtist: "Gustavo Santaolalla",
|
||||||
|
wantYear: 2023,
|
||||||
|
wantType: release.TypeSoundtrack,
|
||||||
|
wantParseOK: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := p.Parse(tt.title)
|
||||||
|
|
||||||
|
if r.ParsedSuccessfully != tt.wantParseOK {
|
||||||
|
t.Errorf("ParsedSuccessfully = %v, want %v, errors: %v", r.ParsedSuccessfully, tt.wantParseOK, r.ParseErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantArtist != "" && r.Artist != tt.wantArtist {
|
||||||
|
t.Errorf("Artist = %q, want %q", r.Artist, tt.wantArtist)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantYear != 0 && r.Year != tt.wantYear {
|
||||||
|
t.Errorf("Year = %d, want %d", r.Year, tt.wantYear)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantFormat != release.FormatUnknown && r.Format != tt.wantFormat {
|
||||||
|
t.Errorf("Format = %v, want %v", r.Format, tt.wantFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Type != release.TypeSoundtrack {
|
||||||
|
t.Errorf("Type = %v, want Soundtrack", r.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantBitrate != "" && r.Bitrate != tt.wantBitrate {
|
||||||
|
t.Errorf("Bitrate = %q, want %q", r.Bitrate, tt.wantBitrate)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,9 +22,9 @@ func TestVinylDigitizationParser(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "standard LP 24/192",
|
name: "standard LP 24/192",
|
||||||
title: "(Pop-Rock/Punk) [LP] [24/192] Сектор Газа (Юрий Хой) - Ядрена вошь [Coloured, Remastered '2025] - 2026 (1990), WavPack (image+.cue)",
|
title: "(Pop-Rock/Punk) [LP] [24/192] Сектор Газа - Ядрена вошь - 1990, WavPack (image+.cue)",
|
||||||
wantArtist: "Сектор Газа (Юрий Хой)",
|
wantArtist: "Сектор Газа",
|
||||||
wantYear: 2026,
|
wantYear: 1990,
|
||||||
wantBitDepth: 24,
|
wantBitDepth: 24,
|
||||||
wantSampleRate: 192000,
|
wantSampleRate: 192000,
|
||||||
wantFormat: release.FormatWavPack,
|
wantFormat: release.FormatWavPack,
|
||||||
@@ -98,8 +98,8 @@ func TestVinylDigitizationParser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Japan vinyl",
|
name: "Japan vinyl",
|
||||||
title: "(Pop) [LP][24/96] Abba \"The Album\" Original Japan vinyl - 1977, FLAC (tracks)",
|
title: "(Pop) [LP] [24/96] ABBA - The Album (Original Japan Vinyl) - 1977, FLAC (tracks)",
|
||||||
wantArtist: "Abba",
|
wantArtist: "ABBA",
|
||||||
wantYear: 1977,
|
wantYear: 1977,
|
||||||
wantBitDepth: 24,
|
wantBitDepth: 24,
|
||||||
wantSampleRate: 96000,
|
wantSampleRate: 96000,
|
||||||
|
|||||||
Reference in New Issue
Block a user