diff --git a/client.go b/client.go index 2ada98e..bff490d 100644 --- a/client.go +++ b/client.go @@ -162,9 +162,9 @@ func (cli *Client) StopSync() { // MakeRequest makes a JSON HTTP request to the given URL. // If "resBody" is not nil, the response body will be json.Unmarshalled into it. // -// Returns the HTTP body as bytes on 2xx. Returns an error if the response is not 2xx. This error -// is an HTTPError which includes the returned HTTP status code and possibly a RespError as the -// WrappedError, if the HTTP body could be decoded as a RespError. +// Returns the HTTP body as bytes on 2xx with a nil error. Returns an error if the response is not 2xx along +// with the HTTP body bytes if it got that far. This error is an HTTPError which includes the returned +// HTTP status code and possibly a RespError as the WrappedError, if the HTTP body could be decoded as a RespError. func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{}, resBody interface{}) ([]byte, error) { var req *http.Request var err error @@ -205,7 +205,7 @@ func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{ msg = msg + ": " + string(contents) } - return nil, HTTPError{ + return contents, HTTPError{ Code: res.StatusCode, Message: msg, WrappedError: wrap, @@ -253,6 +253,46 @@ func (cli *Client) SyncRequest(timeout int, since, filterID string, fullState bo return } +func (cli *Client) register(u string, req *ReqRegister) (resp *RespRegister, uiaResp *RespUserInteractive, err error) { + var bodyBytes []byte + bodyBytes, err = cli.MakeRequest("POST", u, req, nil) + if err != nil { + httpErr, ok := err.(HTTPError) + if !ok { // network error + return + } + if httpErr.Code == 401 { + // body should be RespUserInteractive, if it isn't, fail with the error + err = json.Unmarshal(bodyBytes, &uiaResp) + return + } + return + } + // body should be RespRegister + err = json.Unmarshal(bodyBytes, &resp) + return +} + +// Register makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register +// +// Registers with kind=user. For kind=guest, see RegisterGuest. +func (cli *Client) Register(req *ReqRegister) (resp *RespRegister, uiaResp *RespUserInteractive, err error) { + u := cli.BuildURL("register") + return cli.register(u, req) +} + +// RegisterGuest makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register +// with kind=guest. +// +// For kind=user, see Register. +func (cli *Client) RegisterGuest(req *ReqRegister) (resp *RespRegister, uiaResp *RespUserInteractive, err error) { + query := map[string]string{ + "kind": "guest", + } + u := cli.BuildURLWithQuery([]string{"register"}, query) + return cli.register(u, req) +} + // JoinRoom joins the client to a room ID or alias. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-join-roomidoralias // // If serverName is specified, this will be added as a query param to instruct the homeserver to join via that server. If content is specified, it will diff --git a/requests.go b/requests.go new file mode 100644 index 0000000..8e236f3 --- /dev/null +++ b/requests.go @@ -0,0 +1,11 @@ +package gomatrix + +// ReqRegister is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register +type ReqRegister struct { + Username string `json:"username,omitempty"` + BindEmail bool `json:"bind_email,omitempty"` + Password string `json:"password,omitempty"` + DeviceID string `json:"device_id,omitempty"` + InitialDeviceDisplayName string `json:"initial_device_display_name"` + Auth interface{} `json:"auth,omitempty"` +} diff --git a/responses.go b/responses.go index 1528f97..a4564ad 100644 --- a/responses.go +++ b/responses.go @@ -35,6 +35,24 @@ type RespMediaUpload struct { ContentURI string `json:"content_uri"` } +// RespUserInteractive is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#user-interactive-authentication-api +type RespUserInteractive struct { + Flows []struct { + Stages []string `json:"stages"` + } `json:"flows"` + Params map[string]interface{} `json:"params"` + Session string `json:"string"` +} + +// RespRegister is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register +type RespRegister struct { + AccessToken string `json:"access_token"` + DeviceID string `json:"device_id"` + HomeServer string `json:"home_server"` + RefreshToken string `json:"refresh_token"` + UserID string `json:"user_id"` +} + // RespSync is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync type RespSync struct { NextBatch string `json:"next_batch"`