sheepflix/internal/scanner/scanner.go
2026-08-26 00:34:45 -04:00

79 lines
1.5 KiB
Go

package scanner
import (
"os"
"path/filepath"
"strings"
"time"
)
var videoExtensions = map[string]bool{
".mkv": true,
".mp4": true,
".avi": true,
".m4v": true,
".webm": true,
".ts": true,
".mov": true,
}
type MediaFile struct {
Path string `json:"-"`
RelPath string `json:"rel_path"`
Name string `json:"name"`
Size int64 `json:"size"`
ModTime time.Time `json:"mod_time"`
}
// DisplayName converts a filename into a human-readable display name.
func DisplayName(filename string) string {
name := strings.TrimSuffix(filename, filepath.Ext(filename))
name = strings.ReplaceAll(name, ".", " ")
name = strings.ReplaceAll(name, "_", " ")
return name
}
// Scan recursively walks rootDir and returns all video files found.
func Scan(rootDir string) ([]MediaFile, error) {
var files []MediaFile
err := filepath.WalkDir(rootDir, func(path string, d os.DirEntry, err error) error {
if err != nil {
return nil // skip inaccessible paths
}
if d.IsDir() {
return nil
}
if strings.HasPrefix(d.Name(), "._") {
return nil
}
ext := strings.ToLower(filepath.Ext(d.Name()))
if !videoExtensions[ext] {
return nil
}
info, err := d.Info()
if err != nil {
return nil
}
relPath, err := filepath.Rel(rootDir, path)
if err != nil {
return nil
}
files = append(files, MediaFile{
Path: path,
RelPath: relPath,
Name: DisplayName(d.Name()),
Size: info.Size(),
ModTime: info.ModTime(),
})
return nil
})
return files, err
}