aboutsummaryrefslogblamecommitdiff
path: root/appservice/matrix.go
blob: 96f643a82bf80c75523be79ac047782de0e02374 (plain) (tree)































































































































































































                                                                                                                                        
package appservice

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

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

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.Printf("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.Printf("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.Printf("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.Printf("Response (%d): %#v\n", resp.StatusCode, e)
		return &e
	}

	err = json.NewDecoder(resp.Body).Decode(response)
	if err != nil {
		return err
	}

	log.Printf("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,
		},
	}
	var rep CreateRoomResponse
	err := mxPostApiCall("/_matrix/client/r0/createRoom", &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 mxSendMessageAs(room string, body string, user string) error {
	txn_id := time.Now().UnixNano()
	rq := RoomSendRequest{
		MsgType: "m.text",
		Body: body,
	}
	var rep RoomSendResponse
	err := mxPutApiCall(fmt.Sprintf(
		"/_matrix/client/r0/rooms/%s/send/m.room.message/%d?user_id=%s",
		url.QueryEscape(room), txn_id, url.QueryEscape(user)),
		&rq, &rep)
	return err
}