From 4f8510bac8ac31e7ea59c682ea5da12f05d05fbd Mon Sep 17 00:00:00 2001 From: marcobaobao Date: Mon, 25 Aug 2025 12:48:30 +0200 Subject: [PATCH] fixed twitch authentication --- .gitignore | 1 + server/config/config.go | 6 ++++-- server/middleware/utils.go | 20 ++++++++++++++++++++ server/server.go | 31 ++++++++++++++++++------------- server/twitch/auth.go | 2 +- server/twitch/client.go | 5 +++++ server/twitch/rest.go | 12 ++++++++++++ 7 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 server/middleware/utils.go diff --git a/.gitignore b/.gitignore index 167234e..d7c33d0 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ frontend/.yarn/install-state.gz livestreams.dat .vite/deps archive.txt +twitch-monitor.dat diff --git a/server/config/config.go b/server/config/config.go index 77c9a18..0c9fa61 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -4,6 +4,7 @@ import ( "os" "path/filepath" "sync" + "time" "gopkg.in/yaml.v3" ) @@ -32,8 +33,9 @@ type Config struct { FrontendPath string `yaml:"frontend_path"` AutoArchive bool `yaml:"auto_archive"` Twitch struct { - ClientId string `yaml:"client_id"` - ClientSecret string `yaml:"client_secret"` + ClientId string `yaml:"client_id"` + ClientSecret string `yaml:"client_secret"` + CheckInterval time.Duration `yaml:"check_interval"` } `yaml:"twitch"` } diff --git a/server/middleware/utils.go b/server/middleware/utils.go new file mode 100644 index 0000000..4d6640e --- /dev/null +++ b/server/middleware/utils.go @@ -0,0 +1,20 @@ +package middlewares + +import ( + "net/http" + + "github.com/marcopiovanello/yt-dlp-web-ui/v3/server/config" + "github.com/marcopiovanello/yt-dlp-web-ui/v3/server/openid" +) + +func ApplyAuthenticationByConfig(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if config.Instance().RequireAuth { + Authenticated(next) + } + if config.Instance().UseOpenId { + openid.Middleware(next) + } + next.ServeHTTP(w, r) + }) +} diff --git a/server/server.go b/server/server.go index 02b0604..3a26e00 100644 --- a/server/server.go +++ b/server/server.go @@ -123,10 +123,14 @@ func RunBlocking(rc *RunConfig) { config.Instance().Twitch.ClientSecret, ), ) - go tm.Monitor(context.TODO(), time.Minute*1, twitch.DEFAULT_DOWNLOAD_HANDLER(mdb, mq)) + go tm.Monitor( + context.TODO(), + config.Instance().Twitch.CheckInterval, + twitch.DEFAULT_DOWNLOAD_HANDLER(mdb, mq), + ) go tm.Restore() - srv := newServer(serverConfig{ + scfg := serverConfig{ frontend: rc.App, swagger: rc.Swagger, mdb: mdb, @@ -134,9 +138,11 @@ func RunBlocking(rc *RunConfig) { db: db, lm: lm, tm: tm, - }) + } - go gracefulShutdown(srv, mdb) + srv := newServer(scfg) + + go gracefulShutdown(srv, &scfg) go autoPersist(time.Minute*5, mdb, lm, tm) var ( @@ -200,12 +206,7 @@ func newServer(c serverConfig) *http.Server { // Filebrowser routes r.Route("/filebrowser", func(r chi.Router) { - if config.Instance().RequireAuth { - r.Use(middlewares.Authenticated) - } - if config.Instance().UseOpenId { - r.Use(openid.Middleware) - } + r.Use(middlewares.ApplyAuthenticationByConfig) r.Post("/downloaded", filebrowser.ListDownloaded) r.Post("/delete", filebrowser.DeleteFile) r.Get("/d/{id}", filebrowser.DownloadFile) @@ -249,13 +250,15 @@ func newServer(c serverConfig) *http.Server { // Twitch r.Route("/twitch", func(r chi.Router) { + r.Use(middlewares.ApplyAuthenticationByConfig) + r.Get("/all", twitch.GetMonitoredUsers(c.tm)) r.Post("/add", twitch.MonitorUserHandler(c.tm)) }) return &http.Server{Handler: r} } -func gracefulShutdown(srv *http.Server, db *internal.MemoryDB) { +func gracefulShutdown(srv *http.Server, cfg *serverConfig) { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM, @@ -267,7 +270,9 @@ func gracefulShutdown(srv *http.Server, db *internal.MemoryDB) { slog.Info("shutdown signal received") defer func() { - db.Persist() + cfg.mdb.Persist() + cfg.lm.Persist() + cfg.tm.Persist() stop() srv.Shutdown(context.Background()) @@ -282,6 +287,7 @@ func autoPersist( tm *twitch.Monitor, ) { for { + time.Sleep(d) if err := db.Persist(); err != nil { slog.Warn("failed to persisted session", slog.Any("err", err)) } @@ -294,6 +300,5 @@ func autoPersist( "failed to persisted twitch monitor session", slog.Any("err", err.Error())) } slog.Debug("sucessfully persisted session") - time.Sleep(d) } } diff --git a/server/twitch/auth.go b/server/twitch/auth.go index ca86aea..4a67f35 100644 --- a/server/twitch/auth.go +++ b/server/twitch/auth.go @@ -36,7 +36,7 @@ func NewAuthenticationManager(clientId, clientSecret string) *AuthenticationMana } func (a *AuthenticationManager) GetAccessToken() (*AccessToken, error) { - if a.accesToken != nil && a.accesToken.Expiry.After(time.Now()) { + if a.accesToken != nil && a.accesToken.Token != "" && a.accesToken.Expiry.After(time.Now()) { return a.accesToken, nil } diff --git a/server/twitch/client.go b/server/twitch/client.go index 63227ce..c4c1560 100644 --- a/server/twitch/client.go +++ b/server/twitch/client.go @@ -70,6 +70,11 @@ func (c *Client) PollStream(channel string, liveChannel chan<- *StreamInfo) erro return err } + if len(sr.Data) == 0 { + liveChannel <- &StreamInfo{UserName: channel, IsLive: false} + return nil + } + s := sr.Data[0] started, _ := time.Parse(time.RFC3339, s.StartedAt) diff --git a/server/twitch/rest.go b/server/twitch/rest.go index ec60ab0..7b8238b 100644 --- a/server/twitch/rest.go +++ b/server/twitch/rest.go @@ -3,6 +3,7 @@ package twitch import ( "encoding/json" "net/http" + "slices" ) type addUserReq struct { @@ -26,3 +27,14 @@ func MonitorUserHandler(m *Monitor) http.HandlerFunc { } } } + +func GetMonitoredUsers(m *Monitor) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + it := m.GetMonitoredUsers() + + if err := json.NewEncoder(w).Encode(slices.Collect(it)); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + } +}