refactor: extract session helpers for player identity resolution

Add GetPlayerID, GetUserID, GetNickname to the sessions package.
Remove the inline player-ID-from-session pattern duplicated across
every handler in c4game and snakegame, and the local getPlayerID
helper in snakegame.
This commit is contained in:
Ryan Hamamura
2026-03-02 19:16:09 -10:00
parent 063b03ce25
commit 7eadfbbb0c
3 changed files with 67 additions and 79 deletions

View File

@@ -18,10 +18,10 @@ import (
"github.com/ryanhamamura/c4/features/c4game/components"
"github.com/ryanhamamura/c4/features/c4game/pages"
"github.com/ryanhamamura/c4/game"
"github.com/ryanhamamura/c4/player"
"github.com/ryanhamamura/c4/sessions"
)
func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
func HandleGamePage(store *game.GameStore, sm *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -31,29 +31,20 @@ func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, queries
return
}
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
if playerID == "" {
playerID = player.ID(player.GenerateID(8))
sessions.Put(r.Context(), "player_id", string(playerID))
}
userID := sessions.GetString(r.Context(), "user_id")
if userID != "" {
playerID = player.ID(userID)
}
nickname := sessions.GetString(r.Context(), "nickname")
playerID := sessions.GetPlayerID(sm, r)
userID := sessions.GetUserID(sm, r)
nickname := sessions.GetNickname(sm, r)
// Auto-join if player has a nickname but isn't in the game yet
if nickname != "" && gi.GetPlayerColor(playerID) == 0 {
player := &game.Player{
p := &game.Player{
ID: playerID,
Nickname: nickname,
}
if userID != "" {
player.UserID = &userID
p.UserID = &userID
}
gi.Join(&game.PlayerSession{Player: player})
gi.Join(&game.PlayerSession{Player: p})
}
myColor := gi.GetPlayerColor(playerID)
@@ -86,7 +77,7 @@ func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, queries
}
}
func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sm *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -96,12 +87,7 @@ func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sessions *scs.Sessio
return
}
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
userID := sessions.GetString(r.Context(), "user_id")
if userID != "" {
playerID = player.ID(userID)
}
playerID := sessions.GetPlayerID(sm, r)
myColor := gi.GetPlayerColor(playerID)
sse := datastar.NewSSE(w, r, datastar.WithCompression(
@@ -169,7 +155,7 @@ func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sessions *scs.Sessio
}
}
func HandleDropPiece(store *game.GameStore, sessions *scs.SessionManager) http.HandlerFunc {
func HandleDropPiece(store *game.GameStore, sm *scs.SessionManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -186,12 +172,7 @@ func HandleDropPiece(store *game.GameStore, sessions *scs.SessionManager) http.H
return
}
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
userID := sessions.GetString(r.Context(), "user_id")
if userID != "" {
playerID = player.ID(userID)
}
playerID := sessions.GetPlayerID(sm, r)
myColor := gi.GetPlayerColor(playerID)
if myColor == 0 {
http.Error(w, "not in game", http.StatusForbidden)
@@ -206,7 +187,7 @@ func HandleDropPiece(store *game.GameStore, sessions *scs.SessionManager) http.H
}
}
func HandleSendChat(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
func HandleSendChat(store *game.GameStore, nc *nats.Conn, sm *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -230,12 +211,7 @@ func HandleSendChat(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionM
return
}
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
userID := sessions.GetString(r.Context(), "user_id")
if userID != "" {
playerID = player.ID(userID)
}
playerID := sessions.GetPlayerID(sm, r)
myColor := gi.GetPlayerColor(playerID)
if myColor == 0 {
datastar.NewSSE(w, r)
@@ -272,7 +248,7 @@ func HandleSendChat(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionM
}
}
func HandleSetNickname(store *game.GameStore, sessions *scs.SessionManager) http.HandlerFunc {
func HandleSetNickname(store *game.GameStore, sm *scs.SessionManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -297,23 +273,20 @@ func HandleSetNickname(store *game.GameStore, sessions *scs.SessionManager) http
return
}
sessions.Put(r.Context(), "nickname", signals.Nickname)
sm.Put(r.Context(), "nickname", signals.Nickname)
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
userID := sessions.GetString(r.Context(), "user_id")
if userID != "" {
playerID = player.ID(userID)
}
playerID := sessions.GetPlayerID(sm, r)
userID := sessions.GetUserID(sm, r)
if gi.GetPlayerColor(playerID) == 0 {
player := &game.Player{
p := &game.Player{
ID: playerID,
Nickname: signals.Nickname,
}
if userID != "" {
player.UserID = &userID
p.UserID = &userID
}
gi.Join(&game.PlayerSession{Player: player})
gi.Join(&game.PlayerSession{Player: p})
}
sse := datastar.NewSSE(w, r)
@@ -321,7 +294,7 @@ func HandleSetNickname(store *game.GameStore, sessions *scs.SessionManager) http
}
}
func HandleRematch(store *game.GameStore, sessions *scs.SessionManager) http.HandlerFunc {
func HandleRematch(store *game.GameStore, sm *scs.SessionManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")