Files
HexDeck/backend/api/api.go

139 lines
3.7 KiB
Go

package api
import (
"log/slog"
"net/http"
"github.com/HexCardGames/HexDeck/db"
"github.com/HexCardGames/HexDeck/game"
"github.com/HexCardGames/HexDeck/types"
"github.com/gin-gonic/gin"
)
type ErrorReply struct {
StatusCode string
Message string
}
type StatsReply struct {
TotalGamesPlayed int
RunningGames int
OnlinePlayerCount int
}
type ImprintReply struct {
Content string
}
type CreateRoomReply struct {
JoinCode string
}
type JoinRoomRequest struct {
JoinCode string
Username string
}
type LeaveRoomRequest struct {
SessionToken string
}
func RegisterApi(server *gin.Engine) {
server.GET("/api/stats", func(c *gin.Context) {
stats := game.CalculateStats()
c.JSON(http.StatusOK, StatsReply{
TotalGamesPlayed: db.Conn.QueryGlobalStats().GamesPlayed,
RunningGames: stats.RunningGames,
OnlinePlayerCount: stats.OnlinePlayerCount,
})
})
server.GET("/api/imprint", func(c *gin.Context) {
// TODO: Implement imprint endpoint
c.JSON(http.StatusOK, ImprintReply{
Content: "Not implemented yet",
})
})
server.POST("/api/room/create", func(c *gin.Context) {
request := JoinRoomRequest{}
c.BindJSON(&request)
room := game.CreateRoom()
player := game.JoinRoom(room, request.Username)
player.SetPermissionBit(types.PermissionHost)
slog.Debug("New room created", "username", player.Username, "sessionToken", player.SessionToken, "roomId", room.RoomId.Hex())
c.JSON(http.StatusOK, player)
})
server.POST("/api/room/join", func(c *gin.Context) {
request := JoinRoomRequest{}
c.BindJSON(&request)
room := game.FindRoomByJoinCode(request.JoinCode)
if room == nil {
slog.Debug("Client tried joining room using an invalid joinCode", "joinCode", request.JoinCode)
c.JSON(http.StatusBadRequest, ErrorReply{
StatusCode: "invalid_join_code",
Message: "No valid joinCode was provided",
})
return
}
if room.GameState != types.StateLobby {
slog.Debug("Client tried joining room not in lobby state", "joinCode", request.JoinCode)
c.JSON(http.StatusBadRequest, ErrorReply{
StatusCode: "game_already_running",
Message: "You cannot join this room as the game has already started",
})
return
}
player := game.JoinRoom(room, request.Username)
slog.Debug("New session created", "username", player.Username, "sessionToken", player.SessionToken, "roomId", room.RoomId.Hex(), "joinCode", request.JoinCode)
c.JSON(http.StatusOK, player)
})
server.GET("/api/check/session", func(c *gin.Context) {
sessionToken := c.Query("sessionToken")
if sessionToken == "" {
c.JSON(http.StatusBadRequest, ErrorReply{
StatusCode: "missing_parameter",
Message: "Parameter sessionToken is missing",
})
}
_, player := game.FindSession(sessionToken)
if player == nil {
c.Status(401)
} else {
c.Status(200)
}
})
server.GET("/api/check/joinCode", func(c *gin.Context) {
joinCode := c.Query("JoinCode")
if joinCode == "" {
c.JSON(http.StatusBadRequest, ErrorReply{
StatusCode: "missing_parameter",
Message: "Parameter JoinCode is missing",
})
}
room := game.FindRoomByJoinCode(joinCode)
if room == nil {
c.Status(401)
} else {
c.Status(200)
}
})
server.POST("/api/room/leave", func(c *gin.Context) {
request := LeaveRoomRequest{}
c.BindJSON(&request)
room, player := game.FindSession(request.SessionToken)
if player == nil {
c.JSON(http.StatusBadRequest, ErrorReply{
StatusCode: "invalid_session",
Message: "No user was found with the provided sessionToken",
})
return
}
room.RemovePlayer(*player)
game.OnRoomUpdate(room)
c.Status(http.StatusOK)
})
// Handle WebSocket connections using Socket.io
wsHandler := initWS()
server.Any("/socket.io/", gin.WrapH(wsHandler))
}