aboutsummaryrefslogtreecommitdiff
path: root/vendor/maunium.net/go/gomatrix/client.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/maunium.net/go/gomatrix/client.go')
-rw-r--r--vendor/maunium.net/go/gomatrix/client.go145
1 files changed, 118 insertions, 27 deletions
diff --git a/vendor/maunium.net/go/gomatrix/client.go b/vendor/maunium.net/go/gomatrix/client.go
index 7725ac3..0806138 100644
--- a/vendor/maunium.net/go/gomatrix/client.go
+++ b/vendor/maunium.net/go/gomatrix/client.go
@@ -6,13 +6,16 @@ package gomatrix
import (
"bytes"
"encoding/json"
+ "errors"
"fmt"
"io"
"io/ioutil"
+ "maunium.net/go/maulogger"
"net/http"
"net/url"
"path"
"strconv"
+ "strings"
"sync"
"time"
)
@@ -26,6 +29,7 @@ type Client struct {
Client *http.Client // The underlying HTTP client which will be used to make HTTP requests.
Syncer Syncer // The thing which can process /sync responses
Store Storer // The thing which can store rooms/tokens/ids
+ Logger maulogger.Logger
// The ?user_id= query parameter for application services. This must be set *prior* to calling a method. If this is empty,
// no user_id parameter will be sent.
@@ -39,6 +43,7 @@ type Client struct {
// HTTPError An HTTP Error response, which may wrap an underlying native Go Error.
type HTTPError struct {
WrappedError error
+ RespError *RespError
Message string
Code int
}
@@ -177,6 +182,14 @@ func (cli *Client) StopSync() {
cli.incrementSyncingID()
}
+func (cli *Client) LogRequest(req *http.Request, body string) {
+ if cli.Logger == nil {
+ return
+ }
+
+ cli.Logger.Debugfln("%s %s %s", req.Method, req.URL.Path, body)
+}
+
// MakeRequest makes a JSON HTTP request to the given URL.
// If "resBody" is not nil, the response body will be json.Unmarshalled into it.
//
@@ -186,12 +199,14 @@ func (cli *Client) StopSync() {
func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{}, resBody interface{}) ([]byte, error) {
var req *http.Request
var err error
+ logBody := "{}"
if reqBody != nil {
var jsonStr []byte
jsonStr, err = json.Marshal(reqBody)
if err != nil {
return nil, err
}
+ logBody = string(jsonStr)
req, err = http.NewRequest(method, httpURL, bytes.NewBuffer(jsonStr))
} else {
req, err = http.NewRequest(method, httpURL, nil)
@@ -201,6 +216,7 @@ func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{
return nil, err
}
req.Header.Set("Content-Type", "application/json")
+ cli.LogRequest(req, logBody)
res, err := cli.Client.Do(req)
if res != nil {
defer res.Body.Close()
@@ -211,9 +227,11 @@ func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{
contents, err := ioutil.ReadAll(res.Body)
if res.StatusCode/100 != 2 { // not 2xx
var wrap error
- var respErr RespError
- if _ = json.Unmarshal(contents, &respErr); respErr.ErrCode != "" {
+ respErr := &RespError{}
+ if _ = json.Unmarshal(contents, respErr); respErr.ErrCode != "" {
wrap = respErr
+ } else {
+ respErr = nil
}
// If we failed to decode as RespError, don't just drop the HTTP body, include it in the
@@ -227,6 +245,7 @@ func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{
Code: res.StatusCode,
Message: msg,
WrappedError: wrap,
+ RespError: respErr,
}
}
if err != nil {
@@ -342,7 +361,7 @@ func (cli *Client) RegisterDummy(req *ReqRegister) (*RespRegister, error) {
}
}
if res == nil {
- return nil, fmt.Errorf("registration failed: does this server support m.login.dummy?")
+ return nil, fmt.Errorf("registration failed: does this server support m.login.dummy? ")
}
return res, nil
}
@@ -442,17 +461,38 @@ func (cli *Client) SetAvatarURL(url string) (err error) {
// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
-func (cli *Client) SendMessageEvent(roomID string, eventType string, contentJSON interface{}) (resp *RespSendEvent, err error) {
+func (cli *Client) SendMessageEvent(roomID string, eventType EventType, contentJSON interface{}) (resp *RespSendEvent, err error) {
+ txnID := txnID()
+ urlPath := cli.BuildURL("rooms", roomID, "send", eventType.String(), txnID)
+ _, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
+ return
+}
+
+// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
+// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
+func (cli *Client) SendMassagedMessageEvent(roomID string, eventType EventType, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) {
txnID := txnID()
- urlPath := cli.BuildURL("rooms", roomID, "send", eventType, txnID)
+ urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "send", eventType.String(), txnID}, map[string]string{
+ "ts": strconv.FormatInt(ts, 10),
+ })
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
return
}
// SendStateEvent sends a state event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
-func (cli *Client) SendStateEvent(roomID, eventType, stateKey string, contentJSON interface{}) (resp *RespSendEvent, err error) {
- urlPath := cli.BuildURL("rooms", roomID, "state", eventType, stateKey)
+func (cli *Client) SendStateEvent(roomID string, eventType EventType, stateKey string, contentJSON interface{}) (resp *RespSendEvent, err error) {
+ urlPath := cli.BuildURL("rooms", roomID, "state", eventType.String(), stateKey)
+ _, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
+ return
+}
+
+// SendStateEvent sends a state event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey
+// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
+func (cli *Client) SendMassagedStateEvent(roomID string, eventType EventType, stateKey string, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) {
+ urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "state", eventType.String(), stateKey}, map[string]string{
+ "ts": strconv.FormatInt(ts, 10),
+ })
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
return
}
@@ -460,37 +500,39 @@ func (cli *Client) SendStateEvent(roomID, eventType, stateKey string, contentJSO
// SendText sends an m.room.message event into the given room with a msgtype of m.text
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-text
func (cli *Client) SendText(roomID, text string) (*RespSendEvent, error) {
- return cli.SendMessageEvent(roomID, "m.room.message",
- TextMessage{"m.text", text})
+ return cli.SendMessageEvent(roomID, EventMessage, Content{
+ MsgType: MsgText,
+ Body: text,
+ })
}
// SendImage sends an m.room.message event into the given room with a msgtype of m.image
// See https://matrix.org/docs/spec/client_server/r0.2.0.html#m-image
func (cli *Client) SendImage(roomID, body, url string) (*RespSendEvent, error) {
- return cli.SendMessageEvent(roomID, "m.room.message",
- ImageMessage{
- MsgType: "m.image",
- Body: body,
- URL: url,
- })
+ return cli.SendMessageEvent(roomID, EventMessage, Content{
+ MsgType: MsgImage,
+ Body: body,
+ URL: url,
+ })
}
// SendVideo sends an m.room.message event into the given room with a msgtype of m.video
// See https://matrix.org/docs/spec/client_server/r0.2.0.html#m-video
func (cli *Client) SendVideo(roomID, body, url string) (*RespSendEvent, error) {
- return cli.SendMessageEvent(roomID, "m.room.message",
- VideoMessage{
- MsgType: "m.video",
- Body: body,
- URL: url,
- })
+ return cli.SendMessageEvent(roomID, EventMessage, Content{
+ MsgType: MsgVideo,
+ Body: body,
+ URL: url,
+ })
}
// SendNotice sends an m.room.message event into the given room with a msgtype of m.notice
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-notice
func (cli *Client) SendNotice(roomID, text string) (*RespSendEvent, error) {
- return cli.SendMessageEvent(roomID, "m.room.message",
- TextMessage{"m.notice", text})
+ return cli.SendMessageEvent(roomID, EventMessage, Content{
+ MsgType: MsgNotice,
+ Body: text,
+ })
}
// RedactEvent redacts the given event. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid
@@ -569,11 +611,18 @@ func (cli *Client) UserTyping(roomID string, typing bool, timeout int64) (resp *
return
}
+func (cli *Client) SetPresence(status string) (err error) {
+ req := ReqPresence{Presence: status}
+ u := cli.BuildURL("presence", cli.UserID, "status")
+ _, err = cli.MakeRequest("PUT", u, req, nil)
+ return
+}
+
// StateEvent gets a single state event in a room. It will attempt to JSON unmarshal into the given "outContent" struct with
// the HTTP response body, or return an error.
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey
-func (cli *Client) StateEvent(roomID, eventType, stateKey string, outContent interface{}) (err error) {
- u := cli.BuildURL("rooms", roomID, "state", eventType, stateKey)
+func (cli *Client) StateEvent(roomID string, eventType EventType, stateKey string, outContent interface{}) (err error) {
+ u := cli.BuildURL("rooms", roomID, "state", eventType.String(), stateKey)
_, err = cli.MakeRequest("GET", u, nil, outContent)
return
}
@@ -587,18 +636,48 @@ func (cli *Client) UploadLink(link string) (*RespMediaUpload, error) {
if err != nil {
return nil, err
}
- return cli.UploadToContentRepo(res.Body, res.Header.Get("Content-Type"), res.ContentLength)
+ return cli.Upload(res.Body, res.Header.Get("Content-Type"), res.ContentLength)
+}
+
+func (cli *Client) Download(mxcURL string) (io.ReadCloser, error) {
+ if !strings.HasPrefix(mxcURL, "mxc://") {
+ return nil, errors.New("invalid Matrix content URL")
+ }
+ parts := strings.Split(mxcURL[len("mxc://"):], "/")
+ if len(parts) != 2 {
+ return nil, errors.New("invalid Matrix content URL")
+ }
+ u := cli.BuildBaseURL("_matrix/media/r0/download", parts[0], parts[1])
+ resp, err := cli.Client.Get(u)
+ if err != nil {
+ return nil, err
+ }
+ return resp.Body, nil
+}
+
+func (cli *Client) DownloadBytes(mxcURL string) ([]byte, error) {
+ resp, err := cli.Download(mxcURL)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Close()
+ return ioutil.ReadAll(resp)
+}
+
+func (cli *Client) UploadBytes(data []byte, contentType string) (*RespMediaUpload, error) {
+ return cli.Upload(bytes.NewReader(data), contentType, int64(len(data)))
}
// UploadToContentRepo uploads the given bytes to the content repository and returns an MXC URI.
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-media-r0-upload
-func (cli *Client) UploadToContentRepo(content io.Reader, contentType string, contentLength int64) (*RespMediaUpload, error) {
+func (cli *Client) Upload(content io.Reader, contentType string, contentLength int64) (*RespMediaUpload, error) {
req, err := http.NewRequest("POST", cli.BuildBaseURL("_matrix/media/r0/upload"), content)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", contentType)
req.ContentLength = contentLength
+ cli.LogRequest(req, fmt.Sprintf("%d bytes", contentLength))
res, err := cli.Client.Do(req)
if res != nil {
defer res.Body.Close()
@@ -666,6 +745,18 @@ func (cli *Client) Messages(roomID, from, to string, dir rune, limit int) (resp
return
}
+func (cli *Client) GetEvent(roomID, eventID string) (resp *Event, err error) {
+ urlPath := cli.BuildURL("rooms", roomID, "event", eventID)
+ _, err = cli.MakeRequest("GET", urlPath, nil, &resp)
+ return
+}
+
+func (cli *Client) MarkRead(roomID, eventID string) (err error) {
+ urlPath := cli.BuildURL("rooms", roomID, "receipt", "m.read", eventID)
+ _, err = cli.MakeRequest("POST", urlPath, struct{}{}, nil)
+ return
+}
+
// TurnServer returns turn server details and credentials for the client to use when initiating calls.
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-voip-turnserver
func (cli *Client) TurnServer() (resp *RespTurnServer, err error) {