diff --git a/cmd/gonic/main.go b/cmd/gonic/main.go index 0e38764..5475735 100644 --- a/cmd/gonic/main.go +++ b/cmd/gonic/main.go @@ -4,6 +4,7 @@ import ( "flag" "log" "os" + "time" _ "github.com/jinzhu/gorm/dialects/sqlite" "github.com/peterbourgon/ff" @@ -22,6 +23,7 @@ func main() { listenAddr := set.String("listen-addr", "0.0.0.0:6969", "listen address (optional)") musicPath := set.String("music-path", "", "path to music") dbPath := set.String("db-path", "gonic.db", "path to database (optional)") + scanInterval := set.Int("scan-interval", 0, "interval (in minutes) to automatically scan music (optional)") _ = set.String("config-path", "", "path to config (optional)") if err := ff.Parse(set, os.Args[1:], ff.WithConfigFileFlag("config-path"), @@ -38,11 +40,12 @@ func main() { log.Fatalf("error opening database: %v\n", err) } defer db.Close() - s := server.New( - db, - *musicPath, - *listenAddr, - ) + s := server.New(server.ServerOptions{ + DB: db, + MusicPath: *musicPath, + ListenAddr: *listenAddr, + ScanInterval: time.Duration(*scanInterval) * time.Minute, + }) if err = s.SetupAdmin(); err != nil { log.Fatalf("error setting up admin routes: %v\n", err) } @@ -50,7 +53,7 @@ func main() { log.Fatalf("error setting up subsonic routes: %v\n", err) } log.Printf("starting server at %s", *listenAddr) - if err := s.ListenAndServe(); err != nil { + if err := s.Start(); err != nil { log.Fatalf("error starting server: %v\n", err) } } diff --git a/server/ctrladmin/handlers.go b/server/ctrladmin/handlers.go index 5023a3e..f7c71e5 100644 --- a/server/ctrladmin/handlers.go +++ b/server/ctrladmin/handlers.go @@ -250,10 +250,7 @@ func (c *Controller) ServeUpdateLastFMAPIKeyDo(r *http.Request) *Response { func (c *Controller) ServeStartScanDo(r *http.Request) *Response { defer func() { go func() { - err := scanner. - New(c.DB, c.MusicPath). - Start() - if err != nil { + if err := c.Scanner.Start(); err != nil { log.Printf("error while scanning: %v\n", err) } }() diff --git a/server/ctrlbase/ctrl.go b/server/ctrlbase/ctrl.go index e560049..1b4feee 100644 --- a/server/ctrlbase/ctrl.go +++ b/server/ctrlbase/ctrl.go @@ -6,6 +6,7 @@ import ( "net/http" "senan.xyz/g/gonic/db" + "senan.xyz/g/gonic/scanner" ) type statusWriter struct { @@ -45,6 +46,7 @@ func statusToBlock(code int) string { type Controller struct { DB *db.DB MusicPath string + Scanner *scanner.Scanner } func (c *Controller) WithLogging(next http.Handler) http.Handler { diff --git a/server/ctrlsubsonic/handlers_common.go b/server/ctrlsubsonic/handlers_common.go index 48ed49a..a9e0ba3 100644 --- a/server/ctrlsubsonic/handlers_common.go +++ b/server/ctrlsubsonic/handlers_common.go @@ -79,10 +79,7 @@ func (c *Controller) ServeGetMusicFolders(r *http.Request) *spec.Response { func (c *Controller) ServeStartScan(r *http.Request) *spec.Response { go func() { - err := scanner. - New(c.DB, c.MusicPath). - Start() - if err != nil { + if err := c.Scanner.Start(); err != nil { log.Printf("error while scanning: %v\n", err) } }() diff --git a/server/ctrlsubsonic/testdata/db b/server/ctrlsubsonic/testdata/db index ff3a467..a2ca51d 100644 Binary files a/server/ctrlsubsonic/testdata/db and b/server/ctrlsubsonic/testdata/db differ diff --git a/server/server.go b/server/server.go index 7cc71aa..f7ed694 100644 --- a/server/server.go +++ b/server/server.go @@ -3,6 +3,7 @@ package server import ( "bytes" "fmt" + "log" "net/http" "path/filepath" "time" @@ -11,21 +12,31 @@ import ( "senan.xyz/g/gonic/assets" "senan.xyz/g/gonic/db" + "senan.xyz/g/gonic/scanner" "senan.xyz/g/gonic/server/ctrladmin" "senan.xyz/g/gonic/server/ctrlbase" "senan.xyz/g/gonic/server/ctrlsubsonic" ) -type Server struct { - *http.Server - router *mux.Router - ctrlBase *ctrlbase.Controller +type ServerOptions struct { + DB *db.DB + MusicPath string + ListenAddr string + ScanInterval time.Duration } -func New(db *db.DB, musicPath string, listenAddr string) *Server { +type Server struct { + *http.Server + router *mux.Router + ctrlBase *ctrlbase.Controller + ScanInterval time.Duration +} + +func New(opts ServerOptions) *Server { ctrlBase := &ctrlbase.Controller{ - DB: db, - MusicPath: musicPath, + DB: opts.DB, + MusicPath: opts.MusicPath, + Scanner: scanner.New(opts.DB, opts.MusicPath), } router := mux.NewRouter() router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { @@ -44,16 +55,17 @@ func New(db *db.DB, musicPath string, listenAddr string) *Server { router.Use(ctrlBase.WithLogging) router.Use(ctrlBase.WithCORS) server := &http.Server{ - Addr: listenAddr, + Addr: opts.ListenAddr, Handler: router, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 15 * time.Second, } return &Server{ - Server: server, - router: router, - ctrlBase: ctrlBase, + Server: server, + router: router, + ctrlBase: ctrlBase, + ScanInterval: opts.ScanInterval, } } @@ -134,3 +146,20 @@ func (s *Server) SetupSubsonic() error { rout.Handle("/search2{_:(?:\\.view)?}", ctrl.H(ctrl.ServeSearchTwo)) return nil } + +func (s *Server) scanTick() { + ticker := time.NewTicker(s.ScanInterval) + for range ticker.C { + if err := s.ctrlBase.Scanner.Start(); err != nil { + log.Printf("error while scanner: %v", err) + } + } +} + +func (s *Server) Start() error { + if s.ScanInterval > 0 { + log.Printf("will be scanning at intervals of %s", s.ScanInterval) + go s.scanTick() + } + return s.ListenAndServe() +}