diff --git a/README.md b/README.md index 7b248d9..3cf971e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A new file will be selected if you open `/` directly, or if you click on any dis Browser history is preserved, so you can always go back to any previously displayed media. -Supported file types and extensions are `bmp`, `gif`, `jp[e]g`, `png`, `webp`, `mp4`, `ogv`, `webm`. +Supported file types and extensions are `bmp`, `gif`, `jp[e]g`, `m4a`, `mp3`, `mp4`, `.ogg`, `.ogv`, `png`, `wav`, `webm`, `webp`. Feature requests, code criticism, bug reports, general chit-chat, and unrelated angst accepted at `roulette@seedno.de`. diff --git a/cmd/files.go b/cmd/files.go index f350fa5..8bafb30 100644 --- a/cmd/files.go +++ b/cmd/files.go @@ -44,7 +44,20 @@ type Concurrency struct { var ( ErrNoMediaFound = errors.New("no supported media formats found which match all criteria") - Extensions = [9]string{".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".mp4", ".ogv", ".webm"} + Extensions = [12]string{ + ".bmp", + ".gif", + ".jpeg", + ".jpg", + ".mp3", + ".mp4", + ".ogg", + ".ogv", + ".png", + ".wav", + ".webm", + ".webp", + } ) type Dimensions struct { @@ -144,7 +157,7 @@ func preparePath(path string) string { func appendPath(directory, path string, files *Files, stats *ScanStats, shouldCache bool) error { if shouldCache { - supported, _, _, err := isSupportedFileType(path) + supported, _, _, err := fileType(path) if err != nil { return err } @@ -358,7 +371,7 @@ func pathIsValid(filePath string, paths []string) bool { } } -func isSupportedFileType(path string) (bool, string, string, error) { +func fileType(path string) (bool, string, string, error) { file, err := os.Open(path) switch { case errors.Is(err, os.ErrNotExist): @@ -371,14 +384,30 @@ func isSupportedFileType(path string) (bool, string, string, error) { head := make([]byte, 261) file.Read(head) - extension := strings.TrimPrefix(filepath.Ext(path), ".") + extension := filepath.Ext(path) - fileType := filetype.GetType(extension) + isSupported := false + + for _, e := range Extensions { + if e == extension { + isSupported = true + + break + } + } + + if !isSupported { + return false, "", "", nil + } + + fileType := filetype.GetType(strings.TrimPrefix(extension, ".")) switch { + case filetype.IsAudio(head) && audio: + return true, "audio", fileType.MIME.Value, nil case filetype.IsImage(head): return true, "image", fileType.MIME.Value, nil - case filetype.IsVideo(head): + case filetype.IsVideo(head) && video: return true, "video", fileType.MIME.Value, nil default: return false, "", "", nil @@ -397,7 +426,7 @@ func pathHasSupportedFiles(path string) (bool, error) { case !recursive && info.IsDir() && p != path: return filepath.SkipDir case !info.IsDir(): - supported, _, _, err := isSupportedFileType(p) + supported, _, _, err := fileType(p) if err != nil { return err } @@ -645,7 +674,7 @@ func pickFile(args []string, filters *Filters, sort string, index *Index) (strin filePath := fileList[val] if !fromCache { - supported, _, _, err := isSupportedFileType(filePath) + supported, _, _, err := fileType(filePath) if err != nil { return "", err } diff --git a/cmd/root.go b/cmd/root.go index 8a6f911..96afe5e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,10 +17,11 @@ var ( ) const ( - Version string = "0.61.2" + Version string = "0.62.0" ) var ( + audio bool bind string cache bool cacheFile string @@ -39,6 +40,7 @@ var ( statisticsFile string verbose bool version bool + video bool rootCmd = &cobra.Command{ Use: "roulette [path]...", @@ -75,6 +77,7 @@ func Execute() { } func init() { + rootCmd.Flags().BoolVar(&audio, "audio", false, "additionally support audio files") rootCmd.Flags().StringVarP(&bind, "bind", "b", "0.0.0.0", "address to bind to") rootCmd.Flags().BoolVarP(&cache, "cache", "c", false, "generate directory cache at startup") rootCmd.Flags().StringVar(&cacheFile, "cache-file", "", "path to optional persistent cache file") @@ -93,6 +96,8 @@ func init() { rootCmd.Flags().StringVar(&statisticsFile, "stats-file", "", "path to optional persistent stats file") rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "log accessed files to stdout") rootCmd.Flags().BoolVarP(&version, "version", "V", false, "display version and exit") + rootCmd.Flags().BoolVar(&video, "video", false, "additionally support video files") + rootCmd.Flags().SetInterspersed(true) rootCmd.CompletionOptions.HiddenDefaultCmd = true diff --git a/cmd/web.go b/cmd/web.go index ae9d1eb..317108a 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -974,7 +974,7 @@ func serveMedia(paths []string, Regexes *Regexes, index *Index) httprouter.Handl return } - supported, fileType, mime, err := isSupportedFileType(filePath) + supported, fileType, mime, err := fileType(filePath) if err != nil { fmt.Println(err) @@ -1020,7 +1020,7 @@ func serveMedia(paths []string, Regexes *Regexes, index *Index) httprouter.Handl fileName, dimensions.width, dimensions.height)) - case "video": + default: htmlBody.WriteString(fmt.Sprintf(`%s`, fileName)) } @@ -1033,6 +1033,12 @@ func serveMedia(paths []string, Regexes *Regexes, index *Index) httprouter.Handl } switch fileType { + case "audio": + htmlBody.WriteString(fmt.Sprintf(``, + queryParams, + generateFilePath(filePath), + mime, + fileName)) case "image": htmlBody.WriteString(fmt.Sprintf(`Roulette selected: %s`, queryParams, @@ -1041,16 +1047,16 @@ func serveMedia(paths []string, Regexes *Regexes, index *Index) httprouter.Handl dimensions.height, mime, fileName)) - htmlBody.WriteString(``) case "video": htmlBody.WriteString(fmt.Sprintf(``, queryParams, generateFilePath(filePath), mime, fileName)) - htmlBody.WriteString(``) } + htmlBody.WriteString(``) + _, err = io.WriteString(w, gohtml.Format(htmlBody.String())) if err != nil { fmt.Println(err)