package main import ( "context" "embed" _ "embed" "flag" "fmt" "html/template" "log" "net" "net/http" "os" "os/signal" "path" "strings" "syscall" "ffmpeg.d/pkg/fs" ) //go:embed *.tmpl var TMPL embed.FS func main() { ctx, can := signal.NotifyContext(context.Background(), syscall.SIGINT) defer can() if err := Run(ctx, os.Args[1:]); err != nil { panic(err) } } func Run(ctx context.Context, args []string) error { flags := flag.NewFlagSet(os.Args[0], flag.ContinueOnError) d := flags.String("d", "./testdata/", "directory containing directories of (x.jpg,x.mp4)") p := flags.Int("p", 38080, "port to listen on") if err := flags.Parse(args); err != nil { return err } tmpl, err := template.ParseFS(TMPL, "*.tmpl") if err != nil { return err } s := &http.Server{ Addr: fmt.Sprintf(":%d", *p), Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if strings.HasPrefix(r.URL.Path, "/media/") { http.StripPrefix("/media/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println(r.URL.Path, "vs", *d) http.FileServer(http.Dir(*d)).ServeHTTP(w, r) })).ServeHTTP(w, r) return } type Series struct { HREF string Thumbnail string } ds, err := fs.LsD(*d) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } seriesByKey := map[string]Series{} for _, d := range ds { files, err := fs.LsF(d) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } for _, f := range files { key := strings.Split(path.Base(f), ".")[0] v := seriesByKey[key] switch path.Ext(f) { case ".jpg": v.Thumbnail = path.Join(path.Base(d), path.Base(f)) case ".mp4": v.HREF = path.Join(path.Base(d), path.Base(f)) } seriesByKey[key] = v } } series := []Series{} for _, v := range seriesByKey { series = append(series, v) } if err := tmpl.Execute(w, map[string]any{ "Series": series, }); err != nil { log.Println(err, *d) } }), BaseContext: func(net.Listener) context.Context { return ctx }, } defer s.Shutdown(ctx) errs := make(chan error) go func() { defer close(errs) errs <- s.ListenAndServe() }() select { case err := <-errs: return err case <-ctx.Done(): s.Shutdown(ctx) for range errs { } } return nil }