From 11d6e8c98a83fd4eee33916fb771ef30db4b115d Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 7 May 2024 23:31:25 +0200 Subject: [PATCH 1/2] Introduce handler to get lobby info from passphrase --- api/lobby_info.go | 7 +++++++ api/passphrase.go | 5 +++++ go.mod | 21 +++++++++------------ go.sum | 19 +++++++++++++++++++ handler/handler.go | 34 ++++++++++++++++++++++++++++++++++ utils/passphrase.go | 4 ++++ 6 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 api/lobby_info.go create mode 100644 api/passphrase.go create mode 100644 handler/handler.go diff --git a/api/lobby_info.go b/api/lobby_info.go new file mode 100644 index 0000000..149bf20 --- /dev/null +++ b/api/lobby_info.go @@ -0,0 +1,7 @@ +package api + +import "github.com/google/uuid" + +type LobbyInfo struct { + ID *uuid.UUID `json:"id,omitempty"` +} diff --git a/api/passphrase.go b/api/passphrase.go new file mode 100644 index 0000000..c50b803 --- /dev/null +++ b/api/passphrase.go @@ -0,0 +1,5 @@ +package api + +type Passphrase struct { + Value *string `json:"value,omitempty"` +} diff --git a/go.mod b/go.mod index 4477e2a..901fad6 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module mchess_server go 1.22 require ( - github.com/gin-gonic/gin v1.9.1 + github.com/gin-gonic/gin v1.10.0 github.com/google/uuid v1.6.0 github.com/samber/lo v1.39.0 github.com/stretchr/testify v1.9.0 @@ -13,8 +13,6 @@ require ( require ( github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect - github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -24,23 +22,22 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.20.0 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.1 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect - golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/protobuf v1.34.0 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 04ed76e..81cc336 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -40,6 +42,7 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -62,6 +65,8 @@ github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeB github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg= github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= @@ -85,24 +90,38 @@ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc= golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/handler/handler.go b/handler/handler.go new file mode 100644 index 0000000..f3cf24e --- /dev/null +++ b/handler/handler.go @@ -0,0 +1,34 @@ +package handler + +import ( + "mchess_server/api" + lobbies "mchess_server/lobby_registry" + "mchess_server/utils" + "net/http" + + "github.com/gin-gonic/gin" +) + +func GetLobbyFromPassphraseHandler(c *gin.Context) { + reqPassphrase := api.Passphrase{} + + err := c.ShouldBindJSON(&reqPassphrase) + if err != nil || reqPassphrase.Value == nil || *reqPassphrase.Value == "" { + c.IndentedJSON(http.StatusNotFound, reqPassphrase) + return + } + + lobby := lobbies.GetLobbyRegistry().GetLobbyByPassphrase( + utils.NewPassphraseFromString(*reqPassphrase.Value)) + + if lobby == nil { + c.IndentedJSON(http.StatusNotFound, reqPassphrase) + return + } + + lobbyInfo := api.LobbyInfo{ + ID: &lobby.Uuid, + } + + c.IndentedJSON(http.StatusOK, lobbyInfo) +} diff --git a/utils/passphrase.go b/utils/passphrase.go index d0762d0..1cbf6d9 100644 --- a/utils/passphrase.go +++ b/utils/passphrase.go @@ -20,6 +20,10 @@ func NewPassphrase() Passphrase { return Passphrase(strings.TrimSpace(phrase)) } +func NewPassphraseFromString(s string) Passphrase { + return Passphrase(s) +} + func (p Passphrase) String() string { return string(p) } From d7c4f28f3a4fe491fc1132bc0d1703f59a4207de Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 9 May 2024 22:29:48 +0200 Subject: [PATCH 2/2] Fix endpoint for getting lobby id from passphrase Had to add several helpers (e.g. passphrase ones) to make the endpoint for getting lobby id work. Moved all handler functions into handler package. Added test for getting lobby from passphrase. --- handler/handler.go | 108 ++++++++++++++++++++++++++++++++++++--- handler/handler_test.go | 57 +++++++++++++++++++++ main.go | 104 ++----------------------------------- utils/clean-words.go | 1 - utils/passphrase.go | 28 ++++++++++ utils/passphrase_test.go | 15 ++++++ 6 files changed, 206 insertions(+), 107 deletions(-) create mode 100644 handler/handler_test.go diff --git a/handler/handler.go b/handler/handler.go index f3cf24e..6615f86 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -1,25 +1,49 @@ package handler import ( + "log" "mchess_server/api" + "mchess_server/chess" lobbies "mchess_server/lobby_registry" + "mchess_server/usher" "mchess_server/utils" "net/http" + "sync" "github.com/gin-gonic/gin" + "github.com/google/uuid" ) -func GetLobbyFromPassphraseHandler(c *gin.Context) { - reqPassphrase := api.Passphrase{} +var mut sync.Mutex - err := c.ShouldBindJSON(&reqPassphrase) - if err != nil || reqPassphrase.Value == nil || *reqPassphrase.Value == "" { - c.IndentedJSON(http.StatusNotFound, reqPassphrase) +func HostPrivateGameHandler(c *gin.Context) { + player := chess.NewPlayer(uuid.New()) + u := usher.GetUsher() + + mut.Lock() + defer mut.Unlock() + lobby := u.CreateNewPrivateLobby(player) + u.AddPlayerToLobbyAndStartGameIfFull(player, lobby) + + passphrase := lobby.Passphrase.String() + info := api.PlayerInfo{ + PlayerID: &player.Uuid, + LobbyID: &lobby.Uuid, + Passphrase: &passphrase, + } + c.Header("Access-Control-Allow-Origin", "*") + c.IndentedJSON(http.StatusOK, info) +} + +func GetLobbyForPassphraseHandler(c *gin.Context) { + reqPassphrase := c.Param("phrase") + if reqPassphrase == "" { + c.IndentedJSON(http.StatusBadRequest, reqPassphrase) return } - lobby := lobbies.GetLobbyRegistry().GetLobbyByPassphrase( - utils.NewPassphraseFromString(*reqPassphrase.Value)) + passPhraseWithSpaces := utils.ConvertToPassphraseWithSpaces(reqPassphrase) + lobby := lobbies.GetLobbyRegistry().GetLobbyByPassphrase(passPhraseWithSpaces) if lobby == nil { c.IndentedJSON(http.StatusNotFound, reqPassphrase) @@ -32,3 +56,73 @@ func GetLobbyFromPassphraseHandler(c *gin.Context) { c.IndentedJSON(http.StatusOK, lobbyInfo) } + +func RegisterForRandomGame(c *gin.Context) { + player := chess.NewPlayer(uuid.New()) + usher := usher.GetUsher() + + mut.Lock() + defer mut.Unlock() + lobby := usher.WelcomeNewPlayer(player) + usher.AddPlayerToLobbyAndStartGameIfFull(player, lobby) + + info := api.PlayerInfo{ + PlayerID: &player.Uuid, + LobbyID: &lobby.Uuid, + } + log.Println("responding with info ", info) + + c.Header("Access-Control-Allow-Origin", "*") + c.IndentedJSON(http.StatusOK, info) +} + +func JoinPrivateGame(c *gin.Context) { + req := api.PlayerInfo{} + log.Println(c.Request.Body) + err := c.ShouldBindJSON(&req) + if err != nil || req.Passphrase == nil || *req.Passphrase == "" { + c.IndentedJSON(http.StatusNotFound, req) + } + + u := usher.GetUsher() + + if req.Passphrase != nil && + *req.Passphrase != "" && + req.PlayerID != nil && + req.LobbyID != nil { //is reconnect + lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase)) + _, found := lobby.GetPlayerByUUID(*req.PlayerID) + if found { + c.IndentedJSON( + http.StatusOK, + api.PlayerInfo{ + PlayerID: req.PlayerID, + LobbyID: req.LobbyID, + Passphrase: req.Passphrase, + }) + return + } else { + c.IndentedJSON(http.StatusNotFound, req) + } + } + + player := chess.NewPlayer(uuid.New()) + + mut.Lock() + defer mut.Unlock() + lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase)) + if lobby != nil { + u.AddPlayerToLobbyAndStartGameIfFull(player, lobby) + } else { + c.IndentedJSON(http.StatusNotFound, req) + return + } + + info := api.PlayerInfo{ + PlayerID: &player.Uuid, + LobbyID: &lobby.Uuid, + Passphrase: req.Passphrase, + } + c.Header("Access-Control-Allow-Origin", "*") + c.IndentedJSON(http.StatusOK, info) +} diff --git a/handler/handler_test.go b/handler/handler_test.go new file mode 100644 index 0000000..8e69445 --- /dev/null +++ b/handler/handler_test.go @@ -0,0 +1,57 @@ +package handler + +import ( + "encoding/json" + "mchess_server/api" + "mchess_server/utils" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" +) + +func Test_GetLobbyFromPassphraseHandler(t *testing.T) { + var passphraseURLParameter string + var hostedLobbyId uuid.UUID + + t.Run("host a lobby", func(t *testing.T) { + r1 := httptest.NewRecorder() + ctx1, e1 := gin.CreateTestContext(r1) + e1.GET("/api/hostPrivate", HostPrivateGameHandler) + hostGameRequest, _ := http.NewRequest("GET", "/api/hostPrivate", nil) + ctx1.Request = hostGameRequest + + e1.ServeHTTP(r1, hostGameRequest) + + playerInfo := api.PlayerInfo{} + err := json.Unmarshal(r1.Body.Bytes(), &playerInfo) + assert.NoError(t, err) + + receivedPhrase := *playerInfo.Passphrase + hostedLobbyId = *playerInfo.LobbyID + + passphrase := utils.NewPassphraseFromString(receivedPhrase) + passphraseURLParameter = passphrase.AsURLParam() + }) + + t.Run("see if the lobby can be fetched by using the passphrase", func(t *testing.T) { + r2 := httptest.NewRecorder() + ctx2, engine := gin.CreateTestContext(r2) + engine.GET("/api/getLobbyForPassphrase/:phrase", GetLobbyForPassphraseHandler) + + url := "/api/getLobbyForPassphrase/" + passphraseURLParameter + getLobbyRequest, _ := http.NewRequest("GET", url, nil) + ctx2.Request = getLobbyRequest + + engine.ServeHTTP(r2, getLobbyRequest) + + lobbyInfo := api.LobbyInfo{} + err := json.Unmarshal(r2.Body.Bytes(), &lobbyInfo) + assert.NoError(t, err) + + assert.Equal(t, hostedLobbyId, *lobbyInfo.ID) + }) +} diff --git a/main.go b/main.go index a2432ef..5c7eb8f 100644 --- a/main.go +++ b/main.go @@ -7,22 +7,16 @@ import ( "fmt" "log" "mchess_server/api" - "mchess_server/chess" + "mchess_server/handler" lobbies "mchess_server/lobby_registry" - "mchess_server/usher" - "mchess_server/utils" - "net/http" - "sync" "github.com/gin-gonic/gin" - "github.com/google/uuid" "nhooyr.io/websocket" ) var cert_path = "/etc/letsencrypt/live/chess.sw-gross.de/" var cert_file = cert_path + "fullchain.pem" var key_file = cert_path + "privkey.pem" -var mut sync.Mutex func main() { var debugMode bool @@ -35,10 +29,11 @@ func main() { } router := gin.Default() - router.GET("/api/random", registerForRandomGame) - router.GET("/api/hostPrivate", hostPrivateGame) - router.POST("/api/joinPrivate", joinPrivateGame) + router.GET("/api/random", handler.RegisterForRandomGame) + router.GET("/api/hostPrivate", handler.HostPrivateGameHandler) + router.POST("/api/joinPrivate", handler.JoinPrivateGame) router.GET("/api/ws", registerWebSocketConnection) + router.GET("/api/getLobbyForPassphrase/:phrase", handler.GetLobbyForPassphraseHandler) if debugMode { log.Println("Starting service WITHOUT TLS") @@ -51,95 +46,6 @@ func main() { } } -func registerForRandomGame(c *gin.Context) { - player := chess.NewPlayer(uuid.New()) - usher := usher.GetUsher() - - mut.Lock() - defer mut.Unlock() - lobby := usher.WelcomeNewPlayer(player) - usher.AddPlayerToLobbyAndStartGameIfFull(player, lobby) - - info := api.PlayerInfo{ - PlayerID: &player.Uuid, - LobbyID: &lobby.Uuid, - } - log.Println("responding with info ", info) - - c.Header("Access-Control-Allow-Origin", "*") - c.IndentedJSON(http.StatusOK, info) -} - -func hostPrivateGame(c *gin.Context) { - player := chess.NewPlayer(uuid.New()) - u := usher.GetUsher() - - mut.Lock() - defer mut.Unlock() - lobby := u.CreateNewPrivateLobby(player) - u.AddPlayerToLobbyAndStartGameIfFull(player, lobby) - - passphrase := lobby.Passphrase.String() - info := api.PlayerInfo{ - PlayerID: &player.Uuid, - LobbyID: &lobby.Uuid, - Passphrase: &passphrase, - } - c.Header("Access-Control-Allow-Origin", "*") - c.IndentedJSON(http.StatusOK, info) -} - -func joinPrivateGame(c *gin.Context) { - req := api.PlayerInfo{} - log.Println(c.Request.Body) - err := c.ShouldBindJSON(&req) - if err != nil || req.Passphrase == nil || *req.Passphrase == "" { - c.IndentedJSON(http.StatusNotFound, req) - } - - u := usher.GetUsher() - - if req.Passphrase != nil && - *req.Passphrase != "" && - req.PlayerID != nil && - req.LobbyID != nil { //is reconnect - lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase)) - _, found := lobby.GetPlayerByUUID(*req.PlayerID) - if found { - c.IndentedJSON( - http.StatusOK, - api.PlayerInfo{ - PlayerID: req.PlayerID, - LobbyID: req.LobbyID, - Passphrase: req.Passphrase, - }) - return - } else { - c.IndentedJSON(http.StatusNotFound, req) - } - } - - player := chess.NewPlayer(uuid.New()) - - mut.Lock() - defer mut.Unlock() - lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase)) - if lobby != nil { - u.AddPlayerToLobbyAndStartGameIfFull(player, lobby) - } else { - c.IndentedJSON(http.StatusNotFound, req) - return - } - - info := api.PlayerInfo{ - PlayerID: &player.Uuid, - LobbyID: &lobby.Uuid, - Passphrase: req.Passphrase, - } - c.Header("Access-Control-Allow-Origin", "*") - c.IndentedJSON(http.StatusOK, info) -} - func registerWebSocketConnection(c *gin.Context) { webSocketConn, err := websocket.Accept(c.Writer, c.Request, &websocket.AcceptOptions{OriginPatterns: []string{"chess.sw-gross.de", "localhost:*"}}) if err != nil { diff --git a/utils/clean-words.go b/utils/clean-words.go index 6dda176..2e32f0f 100644 --- a/utils/clean-words.go +++ b/utils/clean-words.go @@ -28006,7 +28006,6 @@ var CleanWords = []string{ "joystick", "joysticks", "jpeg", - "jpn", "juan", "juana", "juanita", diff --git a/utils/passphrase.go b/utils/passphrase.go index 1cbf6d9..7311667 100644 --- a/utils/passphrase.go +++ b/utils/passphrase.go @@ -2,6 +2,7 @@ package utils import ( "strings" + "unicode" ) type Passphrase string @@ -24,6 +25,33 @@ func NewPassphraseFromString(s string) Passphrase { return Passphrase(s) } +func (p Passphrase) AsURLParam() string { + var result string + phraseAsString := p.String() + + segments := strings.Split(phraseAsString, " ") + + for _, segment := range segments { + runes := []rune(segment) + runes[0] = unicode.ToUpper(runes[0]) + result += string(runes) + } + + return result +} + +func ConvertToPassphraseWithSpaces(s string) Passphrase { + result := "" + for _, rune := range s { + if unicode.IsUpper(rune) { + result += " " + } + result += strings.ToLower(string(rune)) + } + + return NewPassphraseFromString(strings.Trim(result, " ")) +} + func (p Passphrase) String() string { return string(p) } diff --git a/utils/passphrase_test.go b/utils/passphrase_test.go index 5876bfa..9af9048 100644 --- a/utils/passphrase_test.go +++ b/utils/passphrase_test.go @@ -19,3 +19,18 @@ func Test_onlyUniqueWords(t *testing.T) { assert.Equal(t, numberOfCleanWords, len(wordsDistribution)) } + +func Test_Passphrase_AsURLParam(t *testing.T) { + phrase := NewPassphraseFromString("this is a Test phrase") + + asParams := phrase.AsURLParam() + + assert.Equal(t, "ThisIsATestPhrase", asParams) +} + +func Test_Passphrase_ConvertToPassphraseWithSpaces(t *testing.T) { + fromURL := "ThisIsATestPhraseWithManyWords" + phrase := ConvertToPassphraseWithSpaces(fromURL) + + assert.Equal(t, NewPassphraseFromString("this is a test phrase with many words"), phrase) +}