package workflows import ( "context" "fmt" "math/rand" "net" "net/http" "os" "gitea.konchin.com/ytshih/inp2025/handlers/wordle" "gitea.konchin.com/ytshih/inp2025/middlewares" "gitea.konchin.com/ytshih/inp2025/types" "github.com/uptrace/bunrouter" "go.uber.org/zap" ) const ( DICT_FILE string = "./dict" ) func generateWordleAns() (string, error) { file, err := os.Open(DICT_FILE) if err != nil { return "", fmt.Errorf("failed to open dictionary, %w", err) } dict := []string{} for { var w string _, err := fmt.Fscanf(file, "%s", &w) if err != nil { break } dict = append(dict, w) } return dict[rand.Intn(len(dict))], nil } func WordleServer(listener net.Listener) types.ShutdownFunc { ans, err := generateWordleAns() if err != nil { panic(fmt.Errorf("failed to generate answer, %w", err)) } logger, _ := zap.Config{ Level: zap.NewAtomicLevelAt(zap.InfoLevel), Encoding: "json", OutputPaths: []string{"logs/wordle-stdout.log"}, ErrorOutputPaths: []string{"logs/wordle-stderr.log"}, EncoderConfig: zap.NewProductionEncoderConfig(), }.Build() undo := zap.ReplaceGlobals(logger) wordleHandlers := wordle.NewHandlers(ans) middlewareHandlers := middlewares.NewHandlers(nil) router := bunrouter.New() apiGroup := router.NewGroup("/api"). Use(middlewareHandlers.ErrorHandler) apiGroup.GET("/state", wordleHandlers.GetState) apiGroup.POST("/guess", wordleHandlers.PostGuess) apiGroup.POST("/end", wordleHandlers.PostEnd) server := &http.Server{ Handler: http.Handler(router), } go func() { fmt.Printf("server up\n") if err := server.Serve(listener); err != http.ErrServerClosed { panic(fmt.Errorf("wordle server failed, %w", err)) } }() return func() { logger.Sync() undo() if err := server.Shutdown(context.Background()); err != nil { panic(fmt.Errorf("failed to shutdown wordle server, %w", err)) } } }