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