refactor: simplify primary artist resolution and remove unused parsing function
This commit is contained in:
+2
-27
@@ -116,8 +116,8 @@ func isValidSpotifyID(id string) bool {
|
|||||||
// resolveSpotifyURL resolves a direct Spotify track URL via ListenBrainz Labs,
|
// resolveSpotifyURL resolves a direct Spotify track URL via ListenBrainz Labs,
|
||||||
// falling back to a search URL. Results are cached.
|
// falling back to a search URL. Results are cached.
|
||||||
func resolveSpotifyURL(track scrobbler.TrackInfo) string {
|
func resolveSpotifyURL(track scrobbler.TrackInfo) string {
|
||||||
primary, _ := parsePrimaryArtist(track.Artist)
|
var primary string
|
||||||
if primary == "" && len(track.Artists) > 0 {
|
if len(track.Artists) > 0 {
|
||||||
primary = track.Artists[0].Name
|
primary = track.Artists[0].Name
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,28 +159,3 @@ func resolveSpotifyURL(track scrobbler.TrackInfo) string {
|
|||||||
pdk.Log(pdk.LogInfo, fmt.Sprintf("Spotify resolution missed, falling back to search URL for %q - %q: %s", primary, track.Title, searchURL))
|
pdk.Log(pdk.LogInfo, fmt.Sprintf("Spotify resolution missed, falling back to search URL for %q - %q: %s", primary, track.Title, searchURL))
|
||||||
return searchURL
|
return searchURL
|
||||||
}
|
}
|
||||||
|
|
||||||
// parsePrimaryArtist returns the primary artist (before "Feat." / "Ft." / "Featuring")
|
|
||||||
// and the optional feat suffix. For artist resolution, only the primary artist is used;
|
|
||||||
// co-artists identified by "Feat.", "Ft.", "Featuring", "&", or "/" are stripped.
|
|
||||||
func parsePrimaryArtist(artist string) (primary, featSuffix string) {
|
|
||||||
artist = strings.TrimSpace(artist)
|
|
||||||
if artist == "" {
|
|
||||||
return "", ""
|
|
||||||
}
|
|
||||||
lower := strings.ToLower(artist)
|
|
||||||
for _, sep := range []string{" feat. ", " ft. ", " featuring "} {
|
|
||||||
if i := strings.Index(lower, sep); i >= 0 {
|
|
||||||
primary = strings.TrimSpace(artist[:i])
|
|
||||||
featSuffix = strings.TrimSpace(artist[i:])
|
|
||||||
return primary, featSuffix
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Split on co-artist separators; take only the first artist.
|
|
||||||
for _, sep := range []string{" & ", " / "} {
|
|
||||||
if i := strings.Index(artist, sep); i >= 0 {
|
|
||||||
return strings.TrimSpace(artist[:i]), ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return artist, ""
|
|
||||||
}
|
|
||||||
|
|||||||
+11
-24
@@ -14,23 +14,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Spotify", func() {
|
var _ = Describe("Spotify", func() {
|
||||||
Describe("parsePrimaryArtist", func() {
|
|
||||||
DescribeTable("extracts primary artist and feat suffix",
|
|
||||||
func(input, expectedPrimary, expectedFeat string) {
|
|
||||||
primary, feat := parsePrimaryArtist(input)
|
|
||||||
Expect(primary).To(Equal(expectedPrimary))
|
|
||||||
Expect(feat).To(Equal(expectedFeat))
|
|
||||||
},
|
|
||||||
Entry("simple artist", "Radiohead", "Radiohead", ""),
|
|
||||||
Entry("Feat. separator", "Wretch 32 Feat. Badness & Ghetts", "Wretch 32", "Feat. Badness & Ghetts"),
|
|
||||||
Entry("Ft. separator", "Artist Ft. Guest", "Artist", "Ft. Guest"),
|
|
||||||
Entry("Featuring separator", "Artist Featuring Someone", "Artist", "Featuring Someone"),
|
|
||||||
Entry("& co-artist", "PinkPantheress & Ice Spice", "PinkPantheress", ""),
|
|
||||||
Entry("/ co-artist", "Artist A / Artist B", "Artist A", ""),
|
|
||||||
Entry("empty string", "", "", ""),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
Describe("spotifySearchURL", func() {
|
Describe("spotifySearchURL", func() {
|
||||||
DescribeTable("constructs Spotify search URL",
|
DescribeTable("constructs Spotify search URL",
|
||||||
func(expectedURL string, terms ...string) {
|
func(expectedURL string, terms ...string) {
|
||||||
@@ -142,9 +125,10 @@ var _ = Describe("Spotify", func() {
|
|||||||
host.CacheMock.On("GetString", spotifyURLKey).Return("https://open.spotify.com/track/cached123", true, nil)
|
host.CacheMock.On("GetString", spotifyURLKey).Return("https://open.spotify.com/track/cached123", true, nil)
|
||||||
|
|
||||||
url := resolveSpotifyURL(scrobbler.TrackInfo{
|
url := resolveSpotifyURL(scrobbler.TrackInfo{
|
||||||
Title: "Karma Police",
|
Title: "Karma Police",
|
||||||
Artist: "Radiohead",
|
Artist: "Radiohead",
|
||||||
Album: "OK Computer",
|
Artists: []scrobbler.ArtistRef{{Name: "Radiohead"}},
|
||||||
|
Album: "OK Computer",
|
||||||
})
|
})
|
||||||
Expect(url).To(Equal("https://open.spotify.com/track/cached123"))
|
Expect(url).To(Equal("https://open.spotify.com/track/cached123"))
|
||||||
})
|
})
|
||||||
@@ -162,6 +146,7 @@ var _ = Describe("Spotify", func() {
|
|||||||
url := resolveSpotifyURL(scrobbler.TrackInfo{
|
url := resolveSpotifyURL(scrobbler.TrackInfo{
|
||||||
Title: "Karma Police",
|
Title: "Karma Police",
|
||||||
Artist: "Radiohead",
|
Artist: "Radiohead",
|
||||||
|
Artists: []scrobbler.ArtistRef{{Name: "Radiohead"}},
|
||||||
Album: "OK Computer",
|
Album: "OK Computer",
|
||||||
MBZRecordingID: "mbid-123",
|
MBZRecordingID: "mbid-123",
|
||||||
})
|
})
|
||||||
@@ -187,6 +172,7 @@ var _ = Describe("Spotify", func() {
|
|||||||
url := resolveSpotifyURL(scrobbler.TrackInfo{
|
url := resolveSpotifyURL(scrobbler.TrackInfo{
|
||||||
Title: "Karma Police",
|
Title: "Karma Police",
|
||||||
Artist: "Radiohead",
|
Artist: "Radiohead",
|
||||||
|
Artists: []scrobbler.ArtistRef{{Name: "Radiohead"}},
|
||||||
Album: "OK Computer",
|
Album: "OK Computer",
|
||||||
MBZRecordingID: "mbid-123",
|
MBZRecordingID: "mbid-123",
|
||||||
})
|
})
|
||||||
@@ -203,16 +189,17 @@ var _ = Describe("Spotify", func() {
|
|||||||
pdk.PDKMock.On("Send", metaReq).Return(pdk.NewStubHTTPResponse(500, nil, []byte(`error`)))
|
pdk.PDKMock.On("Send", metaReq).Return(pdk.NewStubHTTPResponse(500, nil, []byte(`error`)))
|
||||||
|
|
||||||
url := resolveSpotifyURL(scrobbler.TrackInfo{
|
url := resolveSpotifyURL(scrobbler.TrackInfo{
|
||||||
Title: "Karma Police",
|
Title: "Karma Police",
|
||||||
Artist: "Radiohead",
|
Artist: "Radiohead",
|
||||||
Album: "OK Computer",
|
Artists: []scrobbler.ArtistRef{{Name: "Radiohead"}},
|
||||||
|
Album: "OK Computer",
|
||||||
})
|
})
|
||||||
Expect(url).To(HavePrefix("https://open.spotify.com/search/"))
|
Expect(url).To(HavePrefix("https://open.spotify.com/search/"))
|
||||||
Expect(url).To(ContainSubstring("Radiohead"))
|
Expect(url).To(ContainSubstring("Radiohead"))
|
||||||
host.CacheMock.AssertCalled(GinkgoT(), "SetString", spotifyURLKey, mock.Anything, spotifyCacheTTLMiss)
|
host.CacheMock.AssertCalled(GinkgoT(), "SetString", spotifyURLKey, mock.Anything, spotifyCacheTTLMiss)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("uses Artists fallback when primary artist parse is empty", func() {
|
It("uses Artists[0] for primary artist", func() {
|
||||||
host.CacheMock.On("GetString", spotifyURLKey).Return("", false, nil)
|
host.CacheMock.On("GetString", spotifyURLKey).Return("", false, nil)
|
||||||
host.CacheMock.On("SetString", spotifyURLKey, mock.Anything, mock.Anything).Return(nil)
|
host.CacheMock.On("SetString", spotifyURLKey, mock.Anything, mock.Anything).Return(nil)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user