diff options
author | Santo Cariotti <santo@dcariotti.me> | 2025-04-17 10:52:47 +0200 |
---|---|---|
committer | Santo Cariotti <santo@dcariotti.me> | 2025-04-17 10:52:47 +0200 |
commit | 313c96613153d92e4964bef4d2469b09a9505597 (patch) | |
tree | 0b7e8e58f826a2ef4821145eb27b045cf760849c /pkg/ui/views/play_api.go | |
parent | 39a594829ebddc0bc06b92465241439f81fca205 (diff) |
Split views on subfiles
Diffstat (limited to 'pkg/ui/views/play_api.go')
-rw-r--r-- | pkg/ui/views/play_api.go | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/pkg/ui/views/play_api.go b/pkg/ui/views/play_api.go new file mode 100644 index 0000000..1fb02e5 --- /dev/null +++ b/pkg/ui/views/play_api.go @@ -0,0 +1,221 @@ +package views + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + "strconv" + "strings" + + "github.com/boozec/rahanna/internal/api/database" + "github.com/boozec/rahanna/internal/logger" + "github.com/boozec/rahanna/internal/network" + "github.com/boozec/rahanna/pkg/ui/multiplayer" + tea "github.com/charmbracelet/bubbletea" +) + +type responseOk struct { + Name string `json:"name"` + GameID int `json:"id"` + IP string `json:"ip"` + Port int `json:"int"` +} + +// API response types +type playResponse struct { + Ok responseOk + Error string `json:"error"` +} + +type StartGameMsg struct{} + +func (m *PlayModel) handlePlayResponse(msg playResponse) (tea.Model, tea.Cmd) { + m.isLoading = false + m.err = nil + + if msg.Error != "" { + m.err = fmt.Errorf("%s", msg.Error) + if msg.Error == "unauthorized" { + return m, logout(m.width, m.height+1) + } + } else { + m.playName = msg.Ok.Name + m.currentGameId = msg.Ok.GameID + logger, _ := logger.GetLogger() + + callbackCompleted := make(chan bool) + m.network = multiplayer.NewGameNetwork("peer-1", fmt.Sprintf("%s:%d", msg.Ok.IP, msg.Ok.Port), func() error { + close(callbackCompleted) + return nil + }, logger) + + return m, func() tea.Msg { + <-callbackCompleted + return StartGameMsg{} + } + } + + return m, nil +} +func (m *PlayModel) handleGameResponse(msg database.Game) (tea.Model, tea.Cmd) { + m.isLoading = false + m.game = &msg + m.err = nil + ip := strings.Split(m.game.IP2, ":") + if len(ip) == 2 { + localIP := ip[0] + localPort, _ := strconv.ParseInt(ip[1], 10, 32) + + logger, _ := logger.GetLogger() + network := multiplayer.NewGameNetwork("peer-2", fmt.Sprintf("%s:%d", localIP, localPort), func() error { + return nil + }, logger) + + return m, SwitchModelCmd(NewGameModel(m.width, m.height+1, "peer-1", m.game.ID, network)) + } + return m, nil +} + +func (m *PlayModel) handleGamesResponse(msg []database.Game) (tea.Model, tea.Cmd) { + m.isLoading = false + m.games = msg + m.err = nil + m.paginator.SetTotalPages(len(m.games)) + return m, nil +} + +func (m *PlayModel) newGameCallback() tea.Cmd { + return func() tea.Msg { + // Get authorization token + authorization, err := getAuthorizationToken() + if err != nil { + return playResponse{Error: err.Error()} + } + + // Set up network connection + port, err := network.GetRandomAvailablePort() + if err != nil { + return playResponse{Error: err.Error()} + } + + ip := network.GetOutboundIP().String() + // FIXME: ip + ip = "0.0.0.0" + + // Prepare request payload + payload, err := json.Marshal(map[string]string{ + "ip": fmt.Sprintf("%s:%d", ip, port), + }) + if err != nil { + return playResponse{Error: err.Error()} + } + + // Send API request + url := os.Getenv("API_BASE") + "/play" + resp, err := sendAPIRequest("POST", url, payload, authorization) + if err != nil { + return playResponse{Error: err.Error()} + } + defer resp.Body.Close() + + // Handle response + if resp.StatusCode != http.StatusOK { + var response playResponse + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + return playResponse{Error: fmt.Sprintf("HTTP error: %d, unable to decode body", resp.StatusCode)} + } + return playResponse{Error: response.Error} + } + + // Decode successful response + var response struct { + Name string `json:"name"` + ID int `json:"id"` + Error string `json:"error"` + } + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + return playResponse{Error: fmt.Sprintf("Error decoding JSON: %v", err)} + } + + return playResponse{Ok: responseOk{Name: response.Name, GameID: response.ID, IP: ip, Port: port}} + } +} + +func (m PlayModel) enterGame() tea.Cmd { + return func() tea.Msg { + // Get authorization token + authorization, err := getAuthorizationToken() + if err != nil { + return playResponse{Error: err.Error()} + } + + // Set up network connection + port, err := network.GetRandomAvailablePort() + if err != nil { + return playResponse{Error: err.Error()} + } + + ip := network.GetOutboundIP().String() + // FIXME: ip + ip = "0.0.0.0" + + // Prepare request payload + payload, err := json.Marshal(map[string]string{ + "ip": fmt.Sprintf("%s:%d", ip, port), + "name": m.namePrompt.Value(), + }) + if err != nil { + return playResponse{Error: err.Error()} + } + + // Send API request + url := os.Getenv("API_BASE") + "/enter-game" + resp, err := sendAPIRequest("POST", url, payload, authorization) + if err != nil { + return playResponse{Error: err.Error()} + } + defer resp.Body.Close() + + // Handle response + if resp.StatusCode != http.StatusOK { + var response playResponse + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + return playResponse{Error: fmt.Sprintf("HTTP error: %d, unable to decode body", resp.StatusCode)} + } + return playResponse{Error: response.Error} + } + + // Decode successful response + var response database.Game + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + return playResponse{Error: fmt.Sprintf("Error decoding JSON: %v", err)} + } + + return response + } +} + +func (m *PlayModel) fetchGames() tea.Cmd { + return func() tea.Msg { + var games []database.Game + // Get authorization token + authorization, err := getAuthorizationToken() + if err != nil { + return games + } + + // Send API request + url := os.Getenv("API_BASE") + "/play" + resp, err := sendAPIRequest("GET", url, nil, authorization) + if err != nil { + return games + } + defer resp.Body.Close() + + if err := json.NewDecoder(resp.Body).Decode(&games); err != nil { + return []database.Game{} + } + return games + } +} |