diff options
| author | tyropro <[email protected]> | 2026-05-05 23:48:33 +0100 |
|---|---|---|
| committer | tyropro <[email protected]> | 2026-05-05 23:50:32 +0100 |
| commit | 69ee7ccac2cd0bae3b0c7bd42902a4c0738a01ba (patch) | |
| tree | 1f890c7cf1a79a745de92628c36dd0b19f4b970d | |
| parent | ac2d210cd139ee7f84182ec4351a35cf245a9fa8 (diff) | |
refactor: moved all code to an internal module
| -rw-r--r-- | internal/api/api.go | 77 | ||||
| -rw-r--r-- | internal/api/game.go (renamed from game.go) | 4 | ||||
| -rw-r--r-- | internal/api/lobbies.go (renamed from lobbies.go) | 38 | ||||
| -rw-r--r-- | internal/api/players.go (renamed from players.go) | 4 | ||||
| -rw-r--r-- | internal/api/rooms.go (renamed from rooms.go) | 2 | ||||
| -rw-r--r-- | internal/api/state.go (renamed from state.go) | 4 | ||||
| -rw-r--r-- | internal/api/ws.go (renamed from ws.go) | 6 | ||||
| -rw-r--r-- | internal/status/status.go (renamed from status/status.go) | 4 | ||||
| -rw-r--r-- | main.go | 101 |
9 files changed, 123 insertions, 117 deletions
diff --git a/internal/api/api.go b/internal/api/api.go new file mode 100644 index 0000000..640577f --- /dev/null +++ b/internal/api/api.go @@ -0,0 +1,77 @@ +package api + +import ( + "os" + + "github.com/gin-gonic/gin" + _ "github.com/joho/godotenv/autoload" // for .env +) + +func Run() { + staging_mode, release_mode, auto_load_state := getEnv() + + if release_mode { + gin.SetMode(gin.ReleaseMode) + } + + lobby_manager := NewLobbyManager() + ws_manager := NewWsManager() + + if auto_load_state { + lobby_manager.AutoLoadState() + } + + router := setupRouter(lobby_manager, ws_manager) + + // only allow loopback connections on dev + if staging_mode || release_mode { + router.Run(":8080") + } else { + router.Run("127.0.0.1:8080") + } +} + +func getEnv() (bool, bool, bool) { + staging_mode := os.Getenv("MODE") == "staging" + release_mode := os.Getenv("MODE") == "release" + auto_load_state := os.Getenv("AUTO_LOAD_STATE") == "true" + + return staging_mode, release_mode, auto_load_state +} + +func setupRouter(lobby_manager *LobbyManager, ws_manager *WsManager) *gin.Engine { + router := gin.Default() + + // server endpoints + router.POST("/state/save", save_state_endpoint(lobby_manager)) + router.POST("/state/load", load_state_endpoint(lobby_manager)) + + // lobby endpoints + router.GET("/lobbies", get_lobbies(lobby_manager)) + router.GET("/lobbies/:lobby_uuid", get_lobby(lobby_manager)) + + router.POST("/lobbies", create_lobby(lobby_manager)) + + // players endpoints + router.GET("/lobbies/:lobby_uuid/players", get_players(lobby_manager)) + router.GET("/lobbies/:lobby_uuid/players/:player_uuid", get_player(lobby_manager)) + router.GET("/lobbies/:lobby_uuid/players/:player_uuid/valid_moves/:origin_x/:origin_y/:dice_roll", get_player_moves(lobby_manager)) + + router.POST("/lobbies/:lobby_uuid/players/:name", create_player(lobby_manager)) + + router.DELETE("/lobbies/:lobby_uuid/players/:player_uuid", delete_player(lobby_manager)) + + // game endpoints + router.POST("/lobbies/:lobby_uuid/game", create_game(lobby_manager)) + router.POST("/lobbies/:lobby_uuid/suggest", make_suggestion(lobby_manager)) + router.POST("/lobbies/:lobby_uuid/accuse", make_accusation(lobby_manager)) + router.POST("/lobbies/:lobby_uuid/roll/:player_uuid", roll_dice(lobby_manager)) + + router.DELETE("/lobbies/:lobby_uuid/game", delete_game(lobby_manager)) + + // ws endpoints + router.GET("/lobbies/:lobby_uuid/ws/:player_uuid", ws_handler(ws_manager, lobby_manager)) + router.GET("/lobbies/:lobby_uuid/broadcast/:message", broadcast_handler(ws_manager, lobby_manager)) + + return router +} diff --git a/game.go b/internal/api/game.go index 57adff2..da15474 100644 --- a/game.go +++ b/internal/api/game.go @@ -1,7 +1,7 @@ -package main
+package api
import (
- "cluedo-backend/status"
+ "cluedo-backend/internal/status"
"math/rand/v2"
"net/http"
diff --git a/lobbies.go b/internal/api/lobbies.go index de0b617..3776ffb 100644 --- a/lobbies.go +++ b/internal/api/lobbies.go @@ -1,7 +1,8 @@ -package main +package api import ( - "cluedo-backend/status" + "cluedo-backend/internal/status" + "log" "net/http" "sync" @@ -97,35 +98,56 @@ type GetLobbyResponse struct { PlayerCount int `json:"player_count"` } +func (m *LobbyManager) AutoLoadState() error { + log.Println("Attempting to load state from file.") + + lobby_state, err := load_state_from_file() + if err != nil { + log.Println("Failed to load state from file. Skipping.") + return err + } + + m.mu.Lock() + defer m.mu.Unlock() + + m.Lobbies = lobby_state + + log.Println("Loaded state from file.") + + return nil +} + // for use with websockets as the lock only needs to stay on momentarily -func (m *LobbyManager) CheckLobbyExists(lobby_uuid string) (*Lobby, *errResp) { +func (m *LobbyManager) CheckLobbyExists(lobby_uuid string) (*Lobby, *status.ErrorResponse) { m.mu.RLock() defer m.mu.RUnlock() lobby, ok := m.Lobbies[lobby_uuid] if !ok { - return nil, &errResp{Msg: "Lobby not found"} // TODO: change this to standardised error system + err_resp := status.NewErrorResponse(status.LobbyNotFound) + return nil, &err_resp } return &lobby, nil } -func (m *LobbyManager) CheckPlayerExists(lobby_uuid string, player_uuid string) (*Player, *errResp) { +func (m *LobbyManager) CheckPlayerExists(lobby_uuid string, player_uuid string) (*Player, *status.ErrorResponse) { m.mu.RLock() defer m.mu.RUnlock() lobby, ok := m.Lobbies[lobby_uuid] - // TODO: change this to standardised error system if !ok { - return nil, &errResp{Msg: "Lobby not found"} + err_resp := status.NewErrorResponse(status.LobbyNotFound) + return nil, &err_resp } player, ok := lobby.Players[player_uuid] if !ok { - return nil, &errResp{Msg: "Player not found"} + err_resp := status.NewErrorResponse(status.PlayerNotFound) + return nil, &err_resp } return &player, nil diff --git a/players.go b/internal/api/players.go index d0ffd6a..5b3ddcd 100644 --- a/players.go +++ b/internal/api/players.go @@ -1,7 +1,7 @@ -package main +package api import ( - "cluedo-backend/status" + "cluedo-backend/internal/status" "net/http" "slices" "strconv" diff --git a/rooms.go b/internal/api/rooms.go index 16cb378..efb2673 100644 --- a/rooms.go +++ b/internal/api/rooms.go @@ -1,4 +1,4 @@ -package main +package api type Room struct { Name string `json:"name"` diff --git a/state.go b/internal/api/state.go index ebf634e..9baeddf 100644 --- a/state.go +++ b/internal/api/state.go @@ -1,7 +1,7 @@ -package main +package api import ( - "cluedo-backend/status" + "cluedo-backend/internal/status" "encoding/json" "net/http" "os" diff --git a/ws.go b/internal/api/ws.go index 75ab9fd..f8d7252 100644 --- a/ws.go +++ b/internal/api/ws.go @@ -1,4 +1,4 @@ -package main +package api import ( "fmt" @@ -10,6 +10,10 @@ import ( "github.com/gorilla/websocket" ) +type errResp struct { + Msg string `json:"msg"` +} + // websocket manager type WsManager struct { clients map[string]*websocket.Conn // player uuid links to a ws connection (this leads to only 1 ws connection being valid at once) diff --git a/status/status.go b/internal/status/status.go index b15ff53..85981c6 100644 --- a/status/status.go +++ b/internal/status/status.go @@ -30,7 +30,7 @@ type ErrorResponse struct { Type ErrorStatus `json:"type"` } -func newErrorResponse(error_status ErrorStatus) ErrorResponse { +func NewErrorResponse(error_status ErrorStatus) ErrorResponse { return ErrorResponse{ Type: error_status, } @@ -78,7 +78,7 @@ func getHttpStatusCode(error_status ErrorStatus) int { } func GenerateErrorResponse(status ErrorStatus) (int, ErrorResponse) { - response := newErrorResponse(status) + response := NewErrorResponse(status) http_status_code := getHttpStatusCode(status) @@ -1,106 +1,9 @@ package main import ( - "log" - "os" - - "github.com/gin-gonic/gin" - - _ "github.com/joho/godotenv/autoload" // for .env + "cluedo-backend/internal/api" ) -type errResp struct { - Msg string `json:"msg"` -} - func main() { - staging_mode, release_mode, auto_load_state := getEnv() - - // keep debug gin mode when in dev mode or staging - if release_mode { - gin.SetMode(gin.ReleaseMode) - } - - lobby_manager := NewLobbyManager() - - if auto_load_state { - log.Println("Attempting to load state from file.") - lobby_state, err := load_state_from_file() - if err == nil { - // we define this anonymous function so that the - // defer block gets called after we exit the scope - // of this function - func() { - lobby_manager.mu.Lock() - defer lobby_manager.mu.Unlock() - - lobby_manager.Lobbies = lobby_state - }() - - log.Println("Loaded state from file.") - } else { - log.Println("Failed to load state from file. Skipping.") - } - } - - ws_manager := NewWsManager() - router := setupRouter(lobby_manager, ws_manager) - - // only allow loopback connections on dev - if staging_mode || release_mode { - router.Run(":8080") - } else { - router.Run("127.0.0.1:8080") - } -} - -func getEnv() (bool, bool, bool) { - staging_mode := os.Getenv("MODE") == "staging" - release_mode := os.Getenv("MODE") == "release" - auto_load_state := os.Getenv("AUTO_LOAD_STATE") == "true" - - return staging_mode, release_mode, auto_load_state -} - -func setupRouter(lobby_manager *LobbyManager, ws_manager *WsManager) *gin.Engine { - router := gin.Default() - - // server endpoints - router.POST("/state/save", save_state_endpoint(lobby_manager)) - router.POST("/state/load", load_state_endpoint(lobby_manager)) - - // lobby endpoints - router.GET("/lobbies", get_lobbies(lobby_manager)) - router.GET("/lobbies/:lobby_uuid", get_lobby(lobby_manager)) - - router.POST("/lobbies", create_lobby(lobby_manager)) - - // players endpoints - router.GET("/lobbies/:lobby_uuid/players", get_players(lobby_manager)) - router.GET("/lobbies/:lobby_uuid/players/:player_uuid", get_player(lobby_manager)) - router.GET("/lobbies/:lobby_uuid/players/:player_uuid/valid_moves/:origin_x/:origin_y/:dice_roll", get_player_moves(lobby_manager)) - - router.POST("/lobbies/:lobby_uuid/players/:name", create_player(lobby_manager)) - - router.DELETE("/lobbies/:lobby_uuid/players/:player_uuid", delete_player(lobby_manager)) - - // game endpoints - router.POST("/lobbies/:lobby_uuid/game", create_game(lobby_manager)) - router.POST("/lobbies/:lobby_uuid/suggest", make_suggestion(lobby_manager)) - router.POST("/lobbies/:lobby_uuid/accuse", make_accusation(lobby_manager)) - router.POST("/lobbies/:lobby_uuid/roll/:player_uuid", roll_dice(lobby_manager)) - - router.DELETE("/lobbies/:lobby_uuid/game", delete_game(lobby_manager)) - - // ws endpoints - router.GET("/lobbies/:lobby_uuid/ws/:player_uuid", ws_handler(ws_manager, lobby_manager)) - router.GET("/lobbies/:lobby_uuid/broadcast/:message", broadcast_handler(ws_manager, lobby_manager)) - - return router -} - -func NewErrResp(msg string) errResp { - return errResp{ - Msg: msg, - } + api.Run() } |
