aboutsummaryrefslogtreecommitdiff
path: root/mxlib
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2020-02-21 14:27:42 +0100
committerAlex Auvolat <alex@adnab.me>2020-02-21 14:27:42 +0100
commita4cf41536fc8eef743cd330b86e784079100ec6c (patch)
treedaa61f93b76a9966c79ccb481efa32ff49de0bba /mxlib
parent65ddb6be2bafecad1d58bb00cab6020a5df3da0e (diff)
downloadeasybridge-a4cf41536fc8eef743cd330b86e784079100ec6c.tar.gz
easybridge-a4cf41536fc8eef743cd330b86e784079100ec6c.zip
Refactor: move all mx* functions to mxlib/client.go
Diffstat (limited to 'mxlib')
-rw-r--r--mxlib/client.go254
1 files changed, 254 insertions, 0 deletions
diff --git a/mxlib/client.go b/mxlib/client.go
new file mode 100644
index 0000000..2385d6e
--- /dev/null
+++ b/mxlib/client.go
@@ -0,0 +1,254 @@
+package mxlib
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+ "time"
+
+ log "github.com/sirupsen/logrus"
+)
+
+type Client struct {
+ Server string
+ Token string
+ httpClient *http.Client
+}
+
+func NewClient(server string, token string) *Client {
+ tr := &http.Transport{
+ MaxIdleConns: 10,
+ IdleConnTimeout: 30 * time.Second,
+ DisableCompression: true,
+ }
+ return &Client{
+ Server: server,
+ Token: token,
+ httpClient: &http.Client{Transport: tr},
+ }
+}
+
+func (mx *Client) GetApiCall(endpoint string, response interface{}) error {
+ log.Debugf("Matrix GET request: %s\n", endpoint)
+
+ req, err := http.NewRequest("GET", mx.Server+endpoint, nil)
+ if err != nil {
+ return err
+ }
+
+ return mx.DoAndParse(req, response)
+}
+
+func (mx *Client) PutApiCall(endpoint string, data interface{}, response interface{}) error {
+ body, err := json.Marshal(data)
+ if err != nil {
+ return err
+ }
+
+ log.Debugf("Matrix PUT request: %s %s\n", endpoint, string(body))
+
+ req, err := http.NewRequest("PUT", mx.Server+endpoint, bytes.NewBuffer(body))
+ if err != nil {
+ return err
+ }
+ req.Header.Add("Content-Type", "application/json")
+
+ return mx.DoAndParse(req, response)
+}
+
+func (mx *Client) PostApiCall(endpoint string, data interface{}, response interface{}) error {
+ body, err := json.Marshal(data)
+ if err != nil {
+ return err
+ }
+
+ log.Debugf("Matrix POST request: %s %s\n", endpoint, string(body))
+
+ req, err := http.NewRequest("POST", mx.Server+endpoint, bytes.NewBuffer(body))
+ if err != nil {
+ return err
+ }
+ req.Header.Add("Content-Type", "application/json")
+
+ return mx.DoAndParse(req, response)
+}
+
+func (mx *Client) DoAndParse(req *http.Request, response interface{}) error {
+ req.Header.Add("Authorization", "Bearer "+mx.Token)
+
+ resp, err := mx.httpClient.Do(req)
+ if err != nil {
+ return err
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ var e MxError
+ err = json.NewDecoder(resp.Body).Decode(&e)
+ if err != nil {
+ return err
+ }
+ log.Debugf("Response (%d): %#v\n", resp.StatusCode, e)
+ return &e
+ }
+
+ err = json.NewDecoder(resp.Body).Decode(response)
+ if err != nil {
+ return err
+ }
+
+ log.Debugf("Response: %#v\n", response)
+ return nil
+}
+
+// ----
+
+func (mx *Client) RegisterUser(username string) error {
+ req := RegisterRequest{
+ Username: username,
+ }
+ var rep RegisterResponse
+ return mx.PostApiCall("/_matrix/client/r0/register?kind=user", &req, &rep)
+}
+
+func (mx *Client) ProfileDisplayname(userid string, displayname string) error {
+ req := ProfileDisplaynameRequest{
+ Displayname: displayname,
+ }
+ var rep struct{}
+ err := mx.PutApiCall(fmt.Sprintf("/_matrix/client/r0/profile/%s/displayname?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)
+ if err != nil {
+ return "", err
+ }
+ return rep.RoomId, nil
+}
+
+func (mx *Client) CreateRoom(name string, alias string, invite []string) (string, error) {
+ rq := CreateRoomRequest{
+ Preset: "private_chat",
+ RoomAliasName: alias,
+ Name: name,
+ Topic: "",
+ Invite: invite,
+ CreationContent: map[string]interface{}{
+ "m.federate": false,
+ },
+ PowerLevels: map[string]interface{}{
+ "invite": 100,
+ "events": map[string]interface{}{
+ "m.room.topic": 0,
+ "m.room.avatar": 0,
+ },
+ },
+ }
+ var rep CreateRoomResponse
+ err := mx.PostApiCall("/_matrix/client/r0/createRoom", &rq, &rep)
+ if err != nil {
+ return "", err
+ }
+ return rep.RoomId, nil
+}
+
+func (mx *Client) CreateDirectRoomAs(invite []string, as_user string) (string, error) {
+ rq := CreateDirectRoomRequest{
+ Preset: "private_chat",
+ Topic: "",
+ Invite: invite,
+ CreationContent: map[string]interface{}{
+ "m.federate": false,
+ },
+ PowerLevels: map[string]interface{}{
+ "invite": 100,
+ },
+ IsDirect: true,
+ }
+ var rep CreateRoomResponse
+ err := mx.PostApiCall("/_matrix/client/r0/createRoom?user_id="+url.QueryEscape(as_user), &rq, &rep)
+ if err != nil {
+ return "", err
+ }
+ return rep.RoomId, nil
+}
+
+func (mx *Client) RoomInvite(room string, user string) error {
+ rq := RoomInviteRequest{
+ UserId: user,
+ }
+ var rep struct{}
+ err := mx.PostApiCall("/_matrix/client/r0/rooms/"+url.QueryEscape(room)+"/invite", &rq, &rep)
+ return err
+}
+
+func (mx *Client) RoomKick(room string, user string, reason string) error {
+ rq := RoomKickRequest{
+ UserId: user,
+ Reason: reason,
+ }
+ var rep struct{}
+ err := mx.PostApiCall("/_matrix/client/r0/rooms/"+url.QueryEscape(room)+"/kick", &rq, &rep)
+ return err
+}
+
+func (mx *Client) RoomJoinAs(room string, user string) error {
+ rq := struct{}{}
+ var rep RoomJoinResponse
+ err := mx.PostApiCall("/_matrix/client/r0/rooms/"+url.QueryEscape(room)+"/join?user_id="+url.QueryEscape(user), &rq, &rep)
+ return err
+}
+
+func (mx *Client) RoomLeaveAs(room string, user string) error {
+ rq := struct{}{}
+ var rep struct{}
+ err := mx.PostApiCall("/_matrix/client/r0/rooms/"+url.QueryEscape(room)+"/leave?user_id="+url.QueryEscape(user), &rq, &rep)
+ return err
+}
+
+func (mx *Client) SendAs(room string, event_type string, content map[string]interface{}, user string) error {
+ txn_id := time.Now().UnixNano()
+ var rep RoomSendResponse
+ err := mx.PutApiCall(fmt.Sprintf(
+ "/_matrix/client/r0/rooms/%s/send/%s/%d?user_id=%s",
+ url.QueryEscape(room), event_type, txn_id, url.QueryEscape(user)),
+ &content, &rep)
+ return err
+}
+
+func (mx *Client) SendMessageAs(room string, typ string, body string, user string) error {
+ content := map[string]interface{}{
+ "msgtype": typ,
+ "body": body,
+ }
+ return mx.SendAs(room, "m.room.message", content, user)
+}
+
+func (mx *Client) PutStateAs(room string, event_type string, key string, content map[string]interface{}, as_user string) error {
+ var rep RoomSendResponse
+ err := mx.PutApiCall(fmt.Sprintf(
+ "/_matrix/client/r0/rooms/%s/state/%s/%s?user_id=%s",
+ url.QueryEscape(room), event_type, key, url.QueryEscape(as_user)),
+ &content, &rep)
+ return err
+}
+
+func (mx *Client) RoomNameAs(room string, name string, as_user string) error {
+ content := map[string]interface{}{
+ "name": name,
+ }
+ return mx.PutStateAs(room, "m.room.name", "", content, as_user)
+}
+
+func (mx *Client) RoomTopicAs(room string, topic string, as_user string) error {
+ content := map[string]interface{}{
+ "topic": topic,
+ }
+ return mx.PutStateAs(room, "m.room.topic", "", content, as_user)
+}