Merge remote-tracking branch 'origin/master'
Some checks failed
Release / Lint and test (push) Failing after 17m48s
Release / Run Release Please (push) Has been skipped
Release / Build, tag, and publish Docker image (push) Has been skipped
Release / Notify IRC (push) Has been skipped
Nightly Release / Check latest commit (push) Successful in 9s
Nightly Release / Build and release Docker image (push) Has been skipped
Nightly Release / Lint and test (push) Has been skipped
Some checks failed
Release / Lint and test (push) Failing after 17m48s
Release / Run Release Please (push) Has been skipped
Release / Build, tag, and publish Docker image (push) Has been skipped
Release / Notify IRC (push) Has been skipped
Nightly Release / Check latest commit (push) Successful in 9s
Nightly Release / Build and release Docker image (push) Has been skipped
Nightly Release / Lint and test (push) Has been skipped
Conflicts: scanner/scanner.go
This commit is contained in:
@@ -1,83 +0,0 @@
|
||||
package coverresolve
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var DefaultKeywords = []string{
|
||||
"cover",
|
||||
"folder",
|
||||
"front",
|
||||
"albumart",
|
||||
"album",
|
||||
"artist",
|
||||
"scan",
|
||||
}
|
||||
|
||||
// Helper function to extract the number from the filename
|
||||
func extractNumber(filename string) int {
|
||||
re := regexp.MustCompile(`\d+`)
|
||||
matches := re.FindAllString(filename, -1)
|
||||
if len(matches) == 0 {
|
||||
return 0
|
||||
}
|
||||
num, _ := strconv.Atoi(matches[0])
|
||||
return num
|
||||
}
|
||||
|
||||
type CoverAlternative struct {
|
||||
Name string
|
||||
Score int
|
||||
}
|
||||
|
||||
func SelectCover(covers []string) string {
|
||||
if len(covers) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
coverAlternatives := make([]CoverAlternative, 0)
|
||||
|
||||
for _, keyword := range DefaultKeywords {
|
||||
if len(coverAlternatives) > 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for _, cover := range covers {
|
||||
if strings.Contains(strings.ToLower(cover), keyword) {
|
||||
coverAlternatives = append(coverAlternatives, CoverAlternative{
|
||||
Name: cover,
|
||||
Score: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse the integer from the filename
|
||||
// eg. cover(1).jpg will have higher score than cover(114514).jpg
|
||||
for i := range coverAlternatives {
|
||||
coverAlternatives[i].Score -= extractNumber(coverAlternatives[i].Name)
|
||||
}
|
||||
|
||||
// sort by score
|
||||
sort.Slice(coverAlternatives, func(i, j int) bool {
|
||||
return coverAlternatives[i].Score > coverAlternatives[j].Score
|
||||
})
|
||||
|
||||
if len(coverAlternatives) == 0 {
|
||||
return covers[0]
|
||||
}
|
||||
|
||||
return coverAlternatives[0].Name
|
||||
}
|
||||
|
||||
func IsCover(name string) bool {
|
||||
for _, ext := range []string{"jpg", "jpeg", "png", "bmp", "gif"} {
|
||||
if strings.HasSuffix(strings.ToLower(name), "."+ext) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package coverresolve
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsCover(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
filename string
|
||||
expected bool
|
||||
}{
|
||||
{"JPEG file", "Image.jpg", true},
|
||||
{"JPEG file", "image.jpg", true},
|
||||
{"PNG file", "picture.png", true},
|
||||
{"BMP file", "photo.bmp", true},
|
||||
{"GIF file", "animation.gif", true},
|
||||
{"Non-image file", "document.pdf", false},
|
||||
{"Empty file name", "", false},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
result := IsCover(test.filename)
|
||||
if result != test.expected {
|
||||
t.Errorf("Expected IsCover(%q) to be %v, but got %v", test.filename, test.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectCover(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
covers []string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "Empty covers slice",
|
||||
covers: []string{},
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "Covers without keywords or numbers case sensitive",
|
||||
covers: []string{"Cover1.jpg", "cover2.png"},
|
||||
expected: "Cover1.jpg",
|
||||
},
|
||||
{
|
||||
name: "Covers without keywords or numbers",
|
||||
covers: []string{"cover1.jpg", "cover2.png"},
|
||||
expected: "cover1.jpg",
|
||||
},
|
||||
{
|
||||
name: "Covers with keywords and numbers",
|
||||
covers: []string{"cover12.jpg", "cover2.png", "special_cover1.jpg"},
|
||||
expected: "special_cover1.jpg",
|
||||
},
|
||||
{
|
||||
name: "Covers with keywords but without numbers",
|
||||
covers: []string{"cover12.jpg", "cover_keyword.png"},
|
||||
expected: "cover_keyword.png",
|
||||
},
|
||||
{
|
||||
name: "Covers without keywords but with numbers",
|
||||
covers: []string{"cover1.jpg", "cover12.png"},
|
||||
expected: "cover1.jpg",
|
||||
},
|
||||
{
|
||||
name: "Covers with same highest score",
|
||||
covers: []string{"cover1.jpg", "cover2.jpg", "cover_special.jpg"},
|
||||
expected: "cover_special.jpg",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// Mock the DefaultScoreRules
|
||||
result := SelectCover(test.covers)
|
||||
if result != test.expected {
|
||||
t.Errorf("Expected SelectCover(%v) to be %q, but got %q", test.covers, test.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
|
||||
"go.senan.xyz/gonic/db"
|
||||
"go.senan.xyz/gonic/fileutil"
|
||||
"go.senan.xyz/gonic/scanner/coverresolve"
|
||||
"go.senan.xyz/gonic/tags/tagcommon"
|
||||
"go.senan.xyz/wrtag/coverparse"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -267,7 +267,7 @@ func (s *Scanner) scanDir(tx *db.DB, st *State, absPath string) error {
|
||||
}
|
||||
|
||||
var tracks []string
|
||||
var covers []string
|
||||
var cover string
|
||||
for _, item := range items {
|
||||
absPath := filepath.Join(absPath, item.Name())
|
||||
if s.excludePattern != nil && s.excludePattern.MatchString(absPath) {
|
||||
@@ -278,8 +278,8 @@ func (s *Scanner) scanDir(tx *db.DB, st *State, absPath string) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if coverresolve.IsCover(item.Name()) {
|
||||
covers = append(covers, item.Name())
|
||||
if coverparse.IsCover(item.Name()) {
|
||||
coverparse.BestBetween(&cover, item.Name())
|
||||
continue
|
||||
}
|
||||
if s.tagReader.CanRead(absPath) {
|
||||
@@ -288,8 +288,6 @@ func (s *Scanner) scanDir(tx *db.DB, st *State, absPath string) error {
|
||||
}
|
||||
}
|
||||
|
||||
cover := coverresolve.SelectCover(covers)
|
||||
|
||||
pdir, pbasename := filepath.Split(filepath.Dir(relPath))
|
||||
var parent db.Album
|
||||
if err := tx.Where("root_dir=? AND left_path=? AND right_path=?", musicDir, pdir, pbasename).Assign(db.Album{RootDir: musicDir, LeftPath: pdir, RightPath: pbasename}).FirstOrCreate(&parent).Error; err != nil {
|
||||
|
||||
Reference in New Issue
Block a user