package main import ( "errors" "log" "math/rand" "net/http" "os" Cache "tictactoe-api/cache" "time" "github.com/gin-contrib/multitemplate" "github.com/gin-gonic/autotls" "github.com/gin-gonic/gin" ) func setupRender() multitemplate.Renderer { r := multitemplate.NewRenderer() r.AddFromFiles("index", "dist/index.html") r.AddFromFiles("join", "dist/join.html") return r } const charBytes = "abcdefghijkmnopqrstuvwxyz023456789" func generateRandom(n int) string { b := make([]byte, n) for i := range b { b[i] = charBytes[rand.Int63()%int64(len(charBytes))] } return string(b) } func main() { hub := newHub() go hub.run() cache := Cache.NewCache(time.Minute*10, time.Minute) router := gin.Default() router.HTMLRender = setupRender() router.Static("/static", "dist") router.GET("/favicon.ico", func(c *gin.Context) { c.File("dist/favicon.ico") }) router.GET("/ping", func(c *gin.Context) { c.String(http.StatusOK, "pong") }) router.Any("/ws", func(c *gin.Context) { serveWs(hub, c.Writer, c.Request) }) // // // router.GET("/join", func(c *gin.Context) { c.HTML(http.StatusOK, "join", gin.H{ "title": "Play Game", }) }) router.GET("/game", func(c *gin.Context) { c.HTML(http.StatusOK, "index", gin.H{ "title": "Start New Game", }) }) router.POST("/game", func(c *gin.Context) { var game Cache.Game err := c.BindJSON(&game) if err != nil { log.Printf("Error Binding Request %s\n", err.Error()) } count := 0 generate: game.ID = generateRandom(6) _, found := cache.Get(game.ID) if found { count = count + 1 log.Printf("GAME FOUND, trying again: %s\n", game.ID) if count >= 3 { err = errors.New("Could not generate a new game (too many games in progress)") } else { goto generate } } if err != nil { c.JSON(http.StatusConflict, gin.H{ "error": err.Error(), }) } else { game.Turn = &game.Player1.UUID cache.Set(game.ID, game, 0) c.JSON(http.StatusOK, game) } }) router.GET("/game/:gameID", func(c *gin.Context) { gameID := c.Params.ByName("gameID") game, found := cache.Get(gameID) if !found { c.Status(http.StatusNotFound) return } c.JSON(http.StatusOK, game) }) router.POST("/game/:gameID", func(c *gin.Context) { gameID := c.Params.ByName("gameID") game, found := cache.Get(gameID) if !found { c.Status(http.StatusNotFound) return } var updateGame Cache.Game err := c.BindJSON(&updateGame) if err != nil { log.Printf("Error: %s\n", err) } if updateGame.ID != "" { game.ID = updateGame.ID } if updateGame.Player1 != nil { game.Player1 = updateGame.Player1 } if updateGame.Player2 != nil { game.Player2 = updateGame.Player2 } if updateGame.Turn != nil { game.Turn = updateGame.Turn } if (Cache.Matrix{}) != updateGame.Matrix { game.Matrix = updateGame.Matrix } // if updateGame.Draw != nil { // game.Draw = updateGame.Draw // } // if updateGame.Winner != nil { // game.Winner = updateGame.Winner // } // if updateGame.Tally != nil { // game.Tally = append(game.Tally, updateGame.Tally[0]) // } cache.Set(gameID, game, 0) c.JSON(http.StatusOK, game) }) // // // if os.Getenv("GIN_MODE") == "release" { log.Fatal(autotls.Run(router, "tictactoe.l3vi.co")) } else { log.Fatal(router.Run(":80")) } }