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

Conflicts:
	scanner/scanner.go
This commit is contained in:
2024-09-18 17:41:40 +08:00
20 changed files with 162 additions and 239 deletions

View File

@@ -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
}

View File

@@ -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)
}
})
}
}

View File

@@ -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 {