release / govulncheck (push) Successful in 17s
release / web (push) Successful in 1m31s
release / go (push) Successful in 1m51s
release / android (push) Successful in 5m18s
release / integration (push) Successful in 5m23s
release / Build signed APK (releases and dev) (push) Successful in 5m30s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 21s
release / Verify release artifacts (tag releases only) (push) Skipped
MusicBrainz types My Chemical Romance's "Common People (Recorded For BBC Radio 1)" as a plain Single, so a studio-only follow wanted it. Passes now reads the title's qualifier (brackets, or after a dash) for the version it names and treats it as a secondary type; a version no type names, an acoustic or instrumental one, no profile passes. The follow check takes off the list an open follow want the rule now refuses. Judge counts bbc, sessions and unplugged as live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
2.5 KiB
Go
80 lines
2.5 KiB
Go
package release
|
||
|
||
import "strings"
|
||
|
||
// TitleVersion is the version of a recording a release group's title names
|
||
// in its qualifier: the words in brackets, or after a dash. MusicBrainz
|
||
// does not always type such a group: My Chemical Romance's "Common People
|
||
// (Recorded For BBC Radio 1)" is a plain Single (#5573). Typ is the
|
||
// MusicBrainz secondary type the version is, or "" for one no type names
|
||
// (an acoustic or instrumental version); Word is the word that said so.
|
||
type TitleVersion struct {
|
||
Word string
|
||
What string
|
||
Typ string
|
||
}
|
||
|
||
// titleVersions are the qualifier words that name a version, in the order
|
||
// they are looked for: "rough mix" is a demo before "mix" is a remix.
|
||
var titleVersions = []struct {
|
||
words []string
|
||
what string
|
||
typ string
|
||
}{
|
||
{[]string{"demo", "demos", "outtake", "outtakes", "rehearsal", "rough mix"}, "demo recordings", "Demo"},
|
||
{[]string{"live", "bootleg", "bbc", "session", "sessions", "unplugged", "recorded for", "in concert"}, "a live recording", "Live"},
|
||
{[]string{"remix", "remixes", "remixed", "rmx", "mix", "mixes"}, "a remix", "Remix"},
|
||
{[]string{"instrumental", "instrumentals", "acoustic", "karaoke", "acapella", "acappella", "a cappella",
|
||
"drumless", "nightcore", "slowed", "sped up"}, "another version", ""},
|
||
{[]string{"commentary", "interview", "interviews"}, "commentary or interviews", "Interview"},
|
||
}
|
||
|
||
// VersionInTitle reads a release group's title for the version it names,
|
||
// if any. Only the qualifier counts, so "Live Through This" and "Live
|
||
// Forever" name no version.
|
||
func VersionInTitle(title string) (TitleVersion, bool) {
|
||
for _, q := range qualifiers(title) {
|
||
tokens := Tokens(q)
|
||
for _, v := range titleVersions {
|
||
for _, w := range v.words {
|
||
if contains(tokens, strings.Fields(w)) {
|
||
return TitleVersion{Word: w, What: v.what, Typ: v.typ}, true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return TitleVersion{}, false
|
||
}
|
||
|
||
// qualifiers are the parts of a title in brackets, and what follows a
|
||
// spaced dash.
|
||
func qualifiers(title string) []string {
|
||
var out []string
|
||
depth, start := 0, 0
|
||
for i, c := range title {
|
||
switch c {
|
||
case '(', '[', '{':
|
||
if depth == 0 {
|
||
start = i + 1
|
||
}
|
||
depth++
|
||
case ')', ']', '}':
|
||
if depth > 0 {
|
||
depth--
|
||
if depth == 0 {
|
||
out = append(out, title[start:i])
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if depth > 0 {
|
||
out = append(out, title[start:])
|
||
}
|
||
for _, dash := range []string{" - ", " – ", " — "} {
|
||
if i := strings.Index(title, dash); i >= 0 {
|
||
out = append(out, title[i+len(dash):])
|
||
}
|
||
}
|
||
return out
|
||
}
|