From d325629859eaae5772746a5d269dad364b546522 Mon Sep 17 00:00:00 2001 From: Harvey Sanders Date: Tue, 28 Feb 2023 09:52:19 -0500 Subject: [PATCH 1/2] Update API endpoints --- lobbyui/lobby.go | 6 +++--- tui.go | 21 ++++++++------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/lobbyui/lobby.go b/lobbyui/lobby.go index a155334..bf071e9 100644 --- a/lobbyui/lobby.go +++ b/lobbyui/lobby.go @@ -39,7 +39,7 @@ func (m Model) listJams() tea.Cmd { return func() tea.Msg { // Create an HTTP client and make a GET request. c := &http.Client{Timeout: 10 * time.Second} - res, err := c.Get(m.apiURL + "/jam") + res, err := c.Get(m.apiURL + "/jams") if err != nil { // There was an error making our request. Wrap the error we received // in a message and return it. @@ -49,7 +49,7 @@ func (m Model) listJams() tea.Cmd { // Return the HTTP status code // as a message. if res.StatusCode >= 400 { - return rmxerr.ErrMsg{Err: fmt.Errorf("could not get sessions: %d", res.StatusCode)} + return rmxerr.ErrMsg{Err: fmt.Errorf("could not get sessions: %s %d", res.Request.URL.Path, res.StatusCode)} } decoder := json.NewDecoder(res.Body) var resp jamsResp @@ -202,7 +202,7 @@ func jamCreate(baseURL string) tea.Cmd { // Next step would be to show inputs for Jam details // (name, bpm, etc) before creating the Jam. return func() tea.Msg { - resp, err := http.Post(baseURL+"/jam", "application/json", strings.NewReader("{}")) + resp, err := http.Post(baseURL+"/jams", "application/json", strings.NewReader("{}")) if err != nil { return rmxerr.ErrMsg{Err: fmt.Errorf("jamCreate: %v", err)} } diff --git a/tui.go b/tui.go index 69d881b..440d8a7 100644 --- a/tui.go +++ b/tui.go @@ -60,22 +60,17 @@ var ( ) func NewModel(serverHostURL string, debugMode bool) (mainModel, error) { - wsHostURL, err := url.Parse(serverHostURL) - if err != nil { - return mainModel{}, err - } - - wsHostURL.Scheme = "ws" + strings.TrimPrefix(wsHostURL.Scheme, "http") jamModel, err := jamui.New() if err != nil { return mainModel{}, err } + restEndpoint := serverHostURL + "/v0" return mainModel{ curView: lobbyView, - lobby: lobbyui.New(serverHostURL + "/api/v1"), + lobby: lobbyui.New(serverHostURL + "/v0"), jam: jamModel, - RESTendpoint: serverHostURL + "/api/v1", - WSendpoint: wsHostURL.String() + "/ws", + RESTendpoint: restEndpoint, + WSendpoint: strings.Replace(restEndpoint, "http", "ws", 1), log: *log.Default(), }, nil } @@ -135,8 +130,8 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m mainModel) View() string { physicalWidth, _, _ := term.GetSize(int(os.Stdout.Fd())) doc := strings.Builder{} - - status := fmt.Sprintf("server: %s", formatHost(m.RESTendpoint)) + serverLine := fmt.Sprintf("server: %s", formatHost(m.RESTendpoint)) + status := serverLine statusKeyText := "STATUS" rttStats := "--" @@ -156,7 +151,7 @@ func (m mainModel) View() string { } if m.curError != nil { - status = styles.RenderError(fmt.Sprint(m.curError)) + status = styles.RenderError(lipgloss.JoinVertical(lipgloss.Top, fmt.Sprint(m.curError), serverLine)) statusKeyText = "ERROR" } @@ -212,7 +207,7 @@ func bail(err error) { func (m mainModel) jamConnect(jamID string) tea.Cmd { return func() tea.Msg { - jURL := m.WSendpoint + "/jam/" + jamID + jURL := fmt.Sprintf("%s/jams/%s/ws", m.WSendpoint, jamID) ws, _, err := websocket.DefaultDialer.Dial(jURL, nil) if err != nil { return rmxerr.ErrMsg{Err: fmt.Errorf("jamConnect: %v\n%v", jURL, err)} From 7d267054a0f54d1f09037dab279fef684d8d9816 Mon Sep 17 00:00:00 2001 From: Harvey Sanders Date: Tue, 28 Feb 2023 11:20:45 -0500 Subject: [PATCH 2/2] MsgType custom marshaling (not working over WS conn) --- wsmsg/wsmsg.go | 33 +++++++++++++++++++++++++++++++++ wsmsg/wsmsg_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 wsmsg/wsmsg_test.go diff --git a/wsmsg/wsmsg.go b/wsmsg/wsmsg.go index 97a3975..0c252fd 100644 --- a/wsmsg/wsmsg.go +++ b/wsmsg/wsmsg.go @@ -3,6 +3,7 @@ package wsmsg import ( "encoding/json" + "fmt" "github.com/google/uuid" ) @@ -64,3 +65,35 @@ func (e *Envelope) SetPayload(payload any) error { func (e *Envelope) Unwrap(msg any) error { return json.Unmarshal(e.Payload, msg) } + +func (t *MsgType) UnmarshalJSON(data []byte) error { + var rawType string + err := json.Unmarshal(data, &rawType) + if err != nil { + return err + } + + switch rawType { + case "connect": + *t = CONNECT + case "midi": + *t = MIDI + case "text": + *t = TEXT + default: + return fmt.Errorf("unknown type: %s", rawType) + } + return nil +} + +func (t *MsgType) MarshalJSON() ([]byte, error) { + switch *t { + case CONNECT: + return []byte(`"connect"`), nil + case MIDI: + return []byte(`"midi"`), nil + case TEXT: + return []byte(`"text"`), nil + } + return []byte{}, fmt.Errorf("unknown MsgTyp value: %d", *t) +} diff --git a/wsmsg/wsmsg_test.go b/wsmsg/wsmsg_test.go new file mode 100644 index 0000000..4338c3a --- /dev/null +++ b/wsmsg/wsmsg_test.go @@ -0,0 +1,41 @@ +package wsmsg_test + +import ( + "encoding/json" + "testing" + + "github.com/rapidmidiex/rmxtui/wsmsg" + "github.com/stretchr/testify/require" +) + +func TestMsgTypeMarshaling(t *testing.T) { + t.Run("unmarshals type from JSON", func(t *testing.T) { + message := []byte(`{ + "id": "7b0f33ba-8a50-446d-aaa4-4de4aa96fc6c", + "type": "midi", + "payload": { + "state": 1, + "number": 60, + "velocity": 120 + }, + "userId": null +}`) + + var got wsmsg.Envelope + err := json.Unmarshal(message, &got) + require.NoError(t, err) + + require.Equal(t, got.Typ, wsmsg.MIDI) + }) + + t.Run("marshals type to JSON", func(t *testing.T) { + message := wsmsg.Envelope{ + Typ: wsmsg.MIDI, + } + + got, err := json.Marshal(&message) + require.NoError(t, err) + want := `"type":"midi"` + require.Containsf(t, string(got), want, "JSON does not contain [ %s ]\n%s", want, string(got)) + }) +}