package main import ( "context" "fmt" "log" "math" "os" "os/signal" "strconv" "syscall" "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" ) var DEFAULT_HOST string = "0.0.0.0" var DEFAULT_PORT int16 = 8080 func main() { failed := make(chan error) 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 port := DEFAULT_PORT if len(os.Args) > 1 { _port, err := strconv.Atoi(os.Args[1]) if _port > math.MaxUint16 { log.Fatalf("Port must be between 1 and 65535: %d", _port) } port = int16(_port) if err != nil { log.Fatalf("Failed to parse port: %v", err) } } learningService := learning.New(ctx, learning.ServiceConfig{ 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)) }() select { case err := <-failed: log.Fatal(err) case <-ctx.Done(): log.Print("Shutting down...") } }