diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..61d8920 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +TWITCH_CHANNEL_NAME="" +TWITCH_CLIENT_ID="" +TWITCH_CLIENT_SECRET="" diff --git a/.gitignore b/.gitignore index 710c0af..4ca8b3a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ tmp/ learning-title.txt +.env +twitch-auth.json diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..4178135 --- /dev/null +++ b/config/config.go @@ -0,0 +1,13 @@ +package config + +import ( + "os" + "path" +) + +var CONFIG_DIR = func() string { + baseDir, _ := os.UserConfigDir() + dir := path.Join(baseDir, "ari-stream-tools") + if err := os.MkdirAll(dir, 0750); err != nil { panic(err) } + return dir +}() diff --git a/go.mod b/go.mod index e29cd74..1d55ea9 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-yaml v1.19.2 // indirect github.com/godbus/dbus/v5 v5.2.2 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect @@ -32,6 +33,7 @@ require ( golang.org/x/arch v0.22.0 // indirect golang.org/x/crypto v0.48.0 // indirect golang.org/x/net v0.51.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sys v0.41.0 // indirect golang.org/x/text v0.34.0 // indirect google.golang.org/protobuf v1.36.10 // indirect diff --git a/go.sum b/go.sum index 882bc10..4b9205d 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,8 @@ github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7Lk github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= @@ -68,6 +70,8 @@ golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= diff --git a/main.go b/main.go index 33a9a51..4a0542b 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,8 @@ import ( "codeberg.org/arimelody/ari-stream-tools/learning" "codeberg.org/arimelody/ari-stream-tools/music" + "codeberg.org/arimelody/ari-stream-tools/twitch" + "codeberg.org/arimelody/ari-stream-tools/utils/dotenv" "github.com/gin-gonic/gin" ) @@ -23,6 +25,13 @@ func main() { ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer cancel() + envars, err := dotenv.LoadEnv() + if err != nil { + if !os.IsNotExist(err) { + log.Fatalf("Failed to read .env: %v", err) + } + } + gin.SetMode(gin.ReleaseMode) host := DEFAULT_HOST @@ -43,12 +52,30 @@ func main() { TitleFilePath: "learning-title.txt", }) musicService := music.New(ctx) + twitchService, err := twitch.New(ctx, twitch.ServiceOptions{ + Port: port, + ChannelName: dotenv.SafeGet(envars, "TWITCH_CHANNEL_NAME"), + ClientID: dotenv.SafeGet(envars, "TWITCH_CLIENT_ID"), + ClientSecret: dotenv.SafeGet(envars, "TWITCH_CLIENT_SECRET"), + }) + if err != nil { + log.Fatalf("Failed to create Twitch service: %v", err) + } srv := gin.Default() + srv.Use(gin.LoggerWithConfig(gin.LoggerConfig{ + SkipPaths: []string{ + "/twitch/public", + "/music/public", + "/learning/public", + }, + })) learningService.BindRoutes(srv.Group("/learning")) musicService.BindRoutes(srv.Group("/music")) + twitchService.BindRoutes(srv.Group("/twitch")) go musicService.Run(ctx) + go twitchService.Run(ctx) go func() { log.Printf("Now serving at http://%s:%d\n", host, port) failed <- srv.Run(fmt.Sprintf("%s:%d", host, port)) diff --git a/music/music.go b/music/music.go index 3f9c3a5..0a0edb0 100644 --- a/music/music.go +++ b/music/music.go @@ -106,7 +106,7 @@ func (srv *Service) BindRoutes(group *gin.RouterGroup) { }) group.GET("/artwork", func(ctx *gin.Context) { - ctx.Header("cache-control", "no-cache") + ctx.Header("cache-control", "no-store") if srv.track == nil || srv.track.ArtworkURL == "" { http.ServeFileFS(ctx.Writer, ctx.Request, publicFS, "public/default-cover-art.png") diff --git a/music/pages/music.html b/music/pages/music.html index 0f854af..d5d3db9 100644 --- a/music/pages/music.html +++ b/music/pages/music.html @@ -26,6 +26,5 @@ -