aboutsummaryrefslogblamecommitdiff
path: root/appservice/matrix.go
blob: 2c4562e29532243e64cad1fea3c1e51264a988ec (plain) (tree)
1
2
3
4
5
6
7
8
9
10




                  




                       

                                        


                                                         





                                                                                       











                                                                
                                                        














                                                                                  
                                                                         















                                                                                           
                                                                          























                                                                                            
                                                                      







                                                         
                                               










































                                                                                                

                                                     



                                                          
                  








                                                                        





















                                                                                                            
































                                                                                                                                        
                                                                                                  
                                       











                                                                                  
         



                                                                                                                     

                                        


                                                                                  

                  
 






                                                                      





                                                                       
package appservice

import (
	"fmt"
	"net/url"
	"net/http"
	"time"
	"bytes"
	"encoding/json"

	log "github.com/sirupsen/logrus"

	. "git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib"
)

func ezbrMxId() string {
	return fmt.Sprintf("@%s:%s", registration.SenderLocalpart, config.MatrixDomain)
}

// ----

var httpClient *http.Client

func init() {
	tr := &http.Transport{
		MaxIdleConns:       10,
		IdleConnTimeout:    30 * time.Second,
		DisableCompression: true,
	}
	httpClient = &http.Client{Transport: tr}
}

func mxGetApiCall(endpoint string, response interface{}) error {
	log.Debugf("Matrix GET request: %s\n", endpoint)

	req, err := http.NewRequest("GET", config.Server + endpoint, nil)
	if err != nil {
		return err
	}

	return mxDoAndParse(req, response)
}

func mxPutApiCall(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", config.Server + endpoint, bytes.NewBuffer(body))
	if err != nil {
		return err
	}
	req.Header.Add("Content-Type", "application/json")

	return mxDoAndParse(req, response)
}

func mxPostApiCall(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", config.Server + endpoint, bytes.NewBuffer(body))
	if err != nil {
		return err
	}
	req.Header.Add("Content-Type", "application/json")

	return mxDoAndParse(req, response)
}

func mxDoAndParse(req *http.Request, response interface{}) error {
	req.Header.Add("Authorization", "Bearer " + registration.AsToken)

	resp, err := 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 mxRegisterUser(username string) error {
	req := RegisterRequest{
		Username: username,
	}
	var rep RegisterResponse
	return mxPostApiCall("/_matrix/client/r0/register?kind=user", &req, &rep)
}

func mxProfileDisplayname(userid string, displayname string) error {
	req := ProfileDisplaynameRequest{
		Displayname: displayname,
	}
	var rep struct{}
	err := mxPutApiCall(fmt.Sprintf("/_matrix/client/r0/profile/%s/displayname?user_id=%s",
		url.QueryEscape(userid), url.QueryEscape(userid)),
		&req, &rep)
	return err
}

func mxDirectoryRoom(alias string) (string, error) {
	var rep DirectoryRoomResponse
	err := mxGetApiCall("/_matrix/client/r0/directory/room/" + url.QueryEscape(alias), &rep)
	if err != nil {
		return "", err
	}
	return rep.RoomId, nil
}

func mxCreateRoom(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 := mxPostApiCall("/_matrix/client/r0/createRoom", &rq, &rep)
	if err != nil {
		return "", err
	}
	return rep.RoomId, nil
}

func mxCreateDirectRoomAs(name string, invite []string, as_user string) (string, error) {
	rq := CreateRoomNoAliasRequest{
		Preset: "private_chat",
		Name: name,
		Topic: "",
		Invite: invite,
		CreationContent: map[string]interface{} {
			"m.federate": false,
		},
		PowerLevels: map[string]interface{} {
			"invite": 100,
		},
		IsDirect: true,
	}
	var rep CreateRoomResponse
	err := mxPostApiCall("/_matrix/client/r0/createRoom?user_id=" + url.QueryEscape(as_user), &rq, &rep)
	if err != nil {
		return "", err
	}
	return rep.RoomId, nil
}

func mxRoomInvite(room string, user string) error {
	rq := RoomInviteRequest{
		UserId: user,
	}
	var rep struct{}
	err := mxPostApiCall("/_matrix/client/r0/rooms/" + url.QueryEscape(room) + "/invite", &rq, &rep)
	return err
}

func mxRoomKick(room string, user string, reason string) error {
	rq := RoomKickRequest{
		UserId: user,
		Reason: reason,
	}
	var rep struct{}
	err := mxPostApiCall("/_matrix/client/r0/rooms/" + url.QueryEscape(room) + "/kick", &rq, &rep)
	return err
}

func mxRoomJoinAs(room string, user string) error {
	rq := struct{}{}
	var rep RoomJoinResponse
	err := mxPostApiCall("/_matrix/client/r0/rooms/" + url.QueryEscape(room) + "/join?user_id=" + url.QueryEscape(user), &rq, &rep)
	return err
}

func mxRoomLeaveAs(room string, user string) error {
	rq := struct{}{}
	var rep struct{}
	err := mxPostApiCall("/_matrix/client/r0/rooms/" + url.QueryEscape(room) + "/leave?user_id=" + url.QueryEscape(user), &rq, &rep)
	return err
}

func mxSendAs(room string, event_type string, content map[string]interface{}, user string) error {
	txn_id := time.Now().UnixNano()
	var rep RoomSendResponse
	err := mxPutApiCall(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 mxSendMessageAs(room string, typ string, body string, user string) error {
	content := map[string]interface{} {
		"msgtype": typ,
		"body": body,
	}
	return mxSendAs(room, "m.room.message", content, user)
}

func mxPutStateAs(room string, event_type string, key string, content map[string]interface{}, as_user string) error {
	var rep RoomSendResponse
	err := mxPutApiCall(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 mxRoomNameAs(room string, name string, as_user string) error {
	content := map[string]interface{} {
		"name": name,
	}
	return mxPutStateAs(room, "m.room.name", "", content, as_user)
}

func mxRoomTopicAs(room string, topic string, as_user string) error {
	content := map[string]interface{} {
		"topic": topic,
	}
	return mxPutStateAs(room, "m.room.topic", "", content, as_user)
}