diff --git a/main.go b/main.go index 257bcb1..57332e9 100644 --- a/main.go +++ b/main.go @@ -40,31 +40,30 @@ func main() { } } + srv := gin.New() + srv.SetTrustedProxies([]string{"127.0.0.1", "::1"}) + learningService := learning.New(ctx, learning.ServiceConfig{ TitleFilePath: "learning-title.txt", }) - musicService := music.New(ctx) - twitchService, err := twitch.New(ctx, twitch.ServiceOptions{ - Port: port, - }) + learningService.BindRoutes(srv.Group("/learning")) + + musicService, err := music.New(ctx) if err != nil { - log.Fatalf("Failed to create Twitch service: %v", err) + log.Printf("Failed to create music service: %v", err) + } else { + musicService.BindRoutes(srv.Group("/music")) + go musicService.Run(ctx) } - 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")) + twitchService, err := twitch.New(ctx, twitch.ServiceOptions{ Port: port }) + if err != nil { + log.Printf("Failed to create Twitch service: %v", err) + } else { + twitchService.BindRoutes(srv.Group("/twitch")) + go twitchService.Run(ctx) + } - 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 0a0edb0..bab21b8 100644 --- a/music/music.go +++ b/music/music.go @@ -7,6 +7,7 @@ import ( "io" "log" "net/http" + "runtime" "strings" "time" @@ -50,7 +51,11 @@ type ( } ) -func New(ctx context.Context) *Service { +func New(ctx context.Context) (*Service, error) { + if runtime.GOOS != "linux" { + return nil, fmt.Errorf("Platform %s is unsupported", runtime.GOOS) + } + nextTrack := make(chan *trackMetadata) nextPlaying := make(chan bool) @@ -63,7 +68,7 @@ func New(ctx context.Context) *Service { playingBroadcast: broadcast.NewBroadcastChannel(ctx, nextPlaying), } - return srv + return srv, nil } func (srv *Service) BindRoutes(group *gin.RouterGroup) { diff --git a/twitch/twitch.go b/twitch/twitch.go index 6bbb478..64a834a 100644 --- a/twitch/twitch.go +++ b/twitch/twitch.go @@ -6,6 +6,7 @@ import ( "crypto/rand" "embed" "encoding/json" + "errors" "fmt" "io" "log" @@ -73,6 +74,8 @@ const ( ) var DATA_PATH string = path.Join(config.CONFIG_DIR, "twitch") +var CONFIG_FILENAME string = "twitch-config.json" +var CONFIG_PATH string = path.Join(DATA_PATH, CONFIG_FILENAME) //go:embed public var publicFS embed.FS @@ -83,17 +86,31 @@ func New(ctx context.Context, opts ServiceOptions) (*Service, error) { if err := os.MkdirAll(DATA_PATH, 0750); err != nil { panic(err) } if err := os.MkdirAll(path.Join(DATA_PATH, "state"), 0750); err != nil { panic(err) } - var config serviceConfig - if configFile, err := os.OpenFile(path.Join(DATA_PATH, "twitch-config.json"), os.O_CREATE | os.O_RDWR, 0600); err != nil { - log.Fatalf("Failed to open twitch-config.json: %v", err) + config := serviceConfig{} + if configFile, err := os.OpenFile(CONFIG_PATH, os.O_CREATE | os.O_RDWR, 0600); err != nil { + return nil, fmt.Errorf("open %s: %v", CONFIG_FILENAME, err) } else { defer configFile.Close() - // TODO: write template file if empty - if err := json.NewDecoder(configFile).Decode(&config); err != nil { - log.Fatalf("Failed to read twitch-config.json: %v", err) + + stat, err := configFile.Stat() + if err != nil { return nil, fmt.Errorf("stat %s: %v", CONFIG_FILENAME, err) } + + if stat.Size() == 0 { + enc := json.NewEncoder(configFile) + enc.SetIndent("", "\t") + if err := enc.Encode(&config); err != nil { + return nil, fmt.Errorf("write %s: %v", CONFIG_FILENAME, err) + } + return nil, fmt.Errorf("Config file is empty: %s", CONFIG_PATH) + } else if err := json.NewDecoder(configFile).Decode(&config); err != nil { + return nil, fmt.Errorf("decode %s: %v", CONFIG_FILENAME, err) } } + if len(config.ChannelName) == 0 { return nil, errors.New("config: channel_name cannot be empty") } + if len(config.ClientID) == 0 { return nil, errors.New("config: client_id cannot be empty") } + if len(config.ClientSecret) == 0 { return nil, errors.New("config: client_secret cannot be empty") } + latestFollowerC := make(chan string) latestFollowerBroadcast := broadcast.NewBroadcastChannel( ctx, latestFollowerC) @@ -254,7 +271,7 @@ func (srv *Service) BindRoutes(group *gin.RouterGroup) { }) }) - group.GET("/labels", func(ctx *gin.Context) { + group.GET("/label", func(ctx *gin.Context) { http.ServeFileFS(ctx.Writer, ctx.Request, pagesFS, "pages/labels.html") }) }