From b1e8ac2ffb7763550d24f32f7619f58fe9d40715 Mon Sep 17 00:00:00 2001 From: Mateo Greil Date: Tue, 7 May 2024 15:04:59 +0200 Subject: [PATCH] :sparkles: Login --- go.mod | 8 +++ go.sum | 4 ++ internal/protocols/socket/request.go | 13 ++++ internal/protocols/socket/response.go | 8 +++ internal/protocols/stream/request.go | 6 ++ xapi.go | 87 +++++++++++++++++++++++++++ xapi_test.go | 13 ++++ 7 files changed, 139 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/protocols/socket/request.go create mode 100644 internal/protocols/socket/response.go create mode 100644 internal/protocols/stream/request.go create mode 100644 xapi.go create mode 100644 xapi_test.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1fec7ac --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/MateoGreil/xapi-go + +go 1.22.1 + +require ( + github.com/gorilla/websocket v1.5.1 // indirect + golang.org/x/net v0.17.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..272772f --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= diff --git a/internal/protocols/socket/request.go b/internal/protocols/socket/request.go new file mode 100644 index 0000000..e778634 --- /dev/null +++ b/internal/protocols/socket/request.go @@ -0,0 +1,13 @@ +package socket + +type Request struct { + Command string `json:"command"` + Arguments RequestArguments `json:"arguments"` +} + +type RequestArguments interface{} + +type LoginRequestArguments struct { + UserId string `json:"userId"` + Password string `json:"password"` +} diff --git a/internal/protocols/socket/response.go b/internal/protocols/socket/response.go new file mode 100644 index 0000000..b0549b1 --- /dev/null +++ b/internal/protocols/socket/response.go @@ -0,0 +1,8 @@ +package socket + +type LoginResponse struct { + Status bool `json:"status"` + StreamSessionId string `json:"streamSessionId"` + ErrorCode string `json:"errorCode"` + ErrorDescr string `json:"errorDescr"` +} diff --git a/internal/protocols/stream/request.go b/internal/protocols/stream/request.go new file mode 100644 index 0000000..1bac046 --- /dev/null +++ b/internal/protocols/stream/request.go @@ -0,0 +1,6 @@ +package stream + +type Request struct { + Command string `json:"command"` + StreamSessionId string `json:"streamSessionId"` +} diff --git a/xapi.go b/xapi.go new file mode 100644 index 0000000..88e41f1 --- /dev/null +++ b/xapi.go @@ -0,0 +1,87 @@ +package xapi + +import ( + "fmt" + + socket "github.com/MateoGreil/xapi-go/internal/protocols/socket" + stream "github.com/MateoGreil/xapi-go/internal/protocols/stream" + "github.com/gorilla/websocket" +) + +type client struct { + conn *websocket.Conn + streamConn *websocket.Conn + streamSessionId string +} + +const ( + websocketBaseURL = "wss://ws.xtb.com" +) + +func NewClient(userId string, password string, connectionType string) (*client, error) { + var websocketURL string + var websocketStreamURL string + + switch connectionType { + case "demo": + websocketURL = websocketBaseURL + "/demo" + websocketStreamURL = websocketBaseURL + "/demoStream" + case "real": + websocketURL = websocketBaseURL + "/real" + websocketStreamURL = websocketBaseURL + "/realStream" + } + + conn, _, err := websocket.DefaultDialer.Dial(websocketURL, nil) + if err != nil { + return nil, err + } + + streamSessionId, err := login(conn, userId, password) + if err != nil { + return nil, err + } + + streamConn, _, err := websocket.DefaultDialer.Dial(websocketStreamURL, nil) + if err != nil { + return nil, err + } + getKeepAlive(conn, streamSessionId) + + c := &client{ + conn: conn, + streamConn: streamConn, + streamSessionId: streamSessionId, + } + + return c, nil +} + +func login(conn *websocket.Conn, userId string, password string) (string, error) { + request := socket.Request{ + Command: "login", + Arguments: socket.LoginRequestArguments{ + UserId: userId, + Password: password, + }, + } + + fmt.Printf("%+v\n", request) + conn.WriteJSON(request) + response := socket.LoginResponse{} + err := conn.ReadJSON(&response) + if err != nil { + return "", err + } + if response.Status == false { + return "", fmt.Errorf("%+v\n", response.ErrorDescr) + } + return response.StreamSessionId, nil +} + +func getKeepAlive(conn *websocket.Conn, streamSessionId string) { + keepAliveReq := stream.Request{ + Command: "getKeepAlive", + StreamSessionId: streamSessionId, + } + conn.WriteJSON(keepAliveReq) +} diff --git a/xapi_test.go b/xapi_test.go new file mode 100644 index 0000000..51fa144 --- /dev/null +++ b/xapi_test.go @@ -0,0 +1,13 @@ +package xapi + +import ( + "os" + "testing" +) + +func TestNewClient(t *testing.T) { + xapiClient, err := NewClient(os.Getenv("XAPI_USER_ID"), os.Getenv("XAPI_PASSWORD"), "demo") + if err != nil { + t.Error(err) + } +}