diff options
Diffstat (limited to 'mxlib')
-rw-r--r-- | mxlib/api.go | 8 | ||||
-rw-r--r-- | mxlib/client.go | 62 | ||||
-rw-r--r-- | mxlib/mediaobject.go | 54 |
3 files changed, 124 insertions, 0 deletions
diff --git a/mxlib/api.go b/mxlib/api.go index 6dfe56e..7752abc 100644 --- a/mxlib/api.go +++ b/mxlib/api.go @@ -83,3 +83,11 @@ type RoomJoinResponse struct { type RoomSendResponse struct { EventId string `json:"event_id"` } + +type UploadResponse struct { + ContentUri string `json:"content_uri"` +} + +type ProfileAvatarUrl struct { + AvatarUrl string `json:"avatar_url"` +} diff --git a/mxlib/client.go b/mxlib/client.go index 2385d6e..6d87663 100644 --- a/mxlib/client.go +++ b/mxlib/client.go @@ -1,6 +1,7 @@ package mxlib import ( + "strings" "bytes" "encoding/json" "fmt" @@ -9,6 +10,8 @@ import ( "time" log "github.com/sirupsen/logrus" + + "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector" ) type Client struct { @@ -123,6 +126,29 @@ func (mx *Client) ProfileDisplayname(userid string, displayname string) error { return err } +func (mx *Client) ProfileAvatar(userid string, m connector.MediaObject) error { + var mxc *MediaObject + if mxm, ok := m.(*MediaObject); ok { + mxc = mxm + } else { + mxm, err := mx.UploadMedia(m) + if err != nil { + return err + } + mxc = mxm + } + mxc_uri := fmt.Sprintf("mxc://%s/%s", mxc.MxcServer, mxc.MxcMediaId) + + req := ProfileAvatarUrl{ + AvatarUrl: mxc_uri, + } + var rep struct{} + err := mx.PutApiCall(fmt.Sprintf("/_matrix/client/r0/profile/%s/avatar_url?user_id=%s", + url.QueryEscape(userid), url.QueryEscape(userid)), + &req, &rep) + return err +} + func (mx *Client) DirectoryRoom(alias string) (string, error) { var rep DirectoryRoomResponse err := mx.GetApiCall("/_matrix/client/r0/directory/room/"+url.QueryEscape(alias), &rep) @@ -252,3 +278,39 @@ func (mx *Client) RoomTopicAs(room string, topic string, as_user string) error { } return mx.PutStateAs(room, "m.room.topic", "", content, as_user) } + +func (mx *Client) UploadMedia(m connector.MediaObject) (*MediaObject, error) { + reader, err := m.Read() + if err != nil { + return nil, err + } + defer reader.Close() + + req, err := http.NewRequest("POST", + mx.Server+"/_matrix/media/r0/upload?filename="+url.QueryEscape(m.Filename()), + reader) + req.Header.Add("Content-Type", m.Mimetype()) + req.ContentLength = m.Size() + + var resp UploadResponse + err = mx.DoAndParse(req, &resp) + if err != nil { + return nil, err + } + + mxc := strings.Split(strings.Replace(resp.ContentUri, "mxc://", "", 1), "/") + if len(mxc) != 2 { + return nil, fmt.Errorf("Invalid mxc:// returned: %s", resp.ContentUri) + } + + media := &MediaObject{ + mxClient: mx, + filename: m.Filename(), + size: m.Size(), + mimetype: m.Mimetype(), + MxcServer: mxc[0], + MxcMediaId: mxc[1], + } + return media, nil +} + diff --git a/mxlib/mediaobject.go b/mxlib/mediaobject.go new file mode 100644 index 0000000..8a730d2 --- /dev/null +++ b/mxlib/mediaobject.go @@ -0,0 +1,54 @@ +package mxlib + +import ( + "io" + "fmt" + "net/url" + "net/http" +) + +type MediaObject struct { + mxClient *Client + filename string + size int64 + mimetype string + MxcServer string + MxcMediaId string +} + +func (m *MediaObject) Filename() string { + return m.filename +} + +func (m *MediaObject) Size() int64 { + return m.size +} + +func (m *MediaObject) Mimetype() string { + return m.mimetype +} + +func (m *MediaObject) Read() (io.ReadCloser, error) { + req, err := http.NewRequest("GET", m.URL(), nil) + if err != nil { + return nil, err + } + + req.Header.Add("Authorization", "Bearer "+m.mxClient.Token) + + resp, err := m.mxClient.httpClient.Do(req) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("HTTP error %d", resp.StatusCode) + } + + return resp.Body, nil +} + +func (m *MediaObject) URL() string { + return fmt.Sprintf("%s/_matrix/media/r0/download/%s/%s/%s", + m.mxClient.Server, m.MxcServer, m.MxcMediaId, url.QueryEscape(m.filename)) +} |