fuxxy serch + rebuild script

This commit is contained in:
Olive Vaughn 2026-08-26 00:34:45 -04:00
parent 6625e5927e
commit 27ce5a4a92
3 changed files with 73 additions and 5 deletions

View file

@ -134,17 +134,67 @@ func (l *Library) Get(id string) (*MediaItem, string, bool) {
return item, item.fullPath, true
}
// Search returns items whose name contains the query (case-insensitive).
// Search returns items matching the query, ranked by fuzzy match score.
func (l *Library) Search(query string) []MediaItem {
q := strings.ToLower(query)
l.mu.RLock()
defer l.mu.RUnlock()
var results []MediaItem
type scored struct {
item MediaItem
score int
}
var results []scored
for _, item := range l.items {
if strings.Contains(strings.ToLower(item.Name), q) {
results = append(results, item)
name := strings.ToLower(item.Name)
if s := fuzzyScore(name, q); s > 0 {
results = append(results, scored{item, s})
}
}
return results
sort.Slice(results, func(i, j int) bool {
return results[i].score > results[j].score
})
items := make([]MediaItem, len(results))
for i, r := range results {
items[i] = r.item
}
return items
}
// fuzzyScore returns a match score for how well target matches the query.
// Returns 0 if no match. Higher is better.
// Exact substring match gets a big bonus. Otherwise uses subsequence matching
// with bonuses for consecutive chars and word-boundary matches.
func fuzzyScore(target, query string) int {
// exact substring = best possible match
if strings.Contains(target, query) {
return 1000 + len(query)*10
}
// subsequence match with scoring
qi := 0
score := 0
consecutive := 0
for ti := 0; ti < len(target) && qi < len(query); ti++ {
if target[ti] == query[qi] {
score += 10
consecutive++
if consecutive > 1 {
score += consecutive * 5 // bonus for runs
}
// word boundary bonus
if ti == 0 || target[ti-1] == ' ' || target[ti-1] == '.' || target[ti-1] == '_' || target[ti-1] == '-' {
score += 20
}
qi++
} else {
consecutive = 0
}
}
if qi < len(query) {
return 0 // didn't match all query chars
}
return score
}

View file

@ -45,6 +45,10 @@ func Scan(rootDir string) ([]MediaFile, error) {
return nil
}
if strings.HasPrefix(d.Name(), "._") {
return nil
}
ext := strings.ToLower(filepath.Ext(d.Name()))
if !videoExtensions[ext] {
return nil