Matrix/entities/event/eventController.go
2020-11-27 05:52:27 +01:00

847 lines
23 KiB
Go

package event
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"log"
"math/rand"
"net/http"
"strconv"
"time"
"git.nutfactory.org/hoernschen/Matrix/config"
"git.nutfactory.org/hoernschen/Matrix/entities/device"
"git.nutfactory.org/hoernschen/Matrix/entities/user"
"git.nutfactory.org/hoernschen/Matrix/utils"
"github.com/cenkalti/backoff/v4"
"github.com/gorilla/mux"
)
func New(
roomId string,
sender string,
origin string,
timestamp int64,
eventType string,
stateKey string,
content string,
txnId string,
) (err error, newEvent *Event) {
err, eventId := utils.CreateUUID()
if err != nil {
return
}
id := generateEventId(eventId)
newEvent = &Event{
Id: id,
RoomId: roomId,
Sender: sender,
Origin: origin,
Timestamp: timestamp,
EventType: eventType,
StateKey: stateKey,
Content: content,
Unsigned: UnsignedData{
TransactionId: txnId,
},
}
newEvent.AuthEventHashes, err = GetAuthEvents(newEvent)
if err != nil {
return
}
if eventType != "m.room.create" {
var depth int
newEvent.PrevEventHashes, depth, err = ReadEventsWithoutChild(roomId)
if err != nil {
return
}
newEvent.Depth = depth + 1
}
newEvent.AuthEventHashes, err = GetAuthEvents(newEvent)
if err != nil {
return
}
newEventBytesForHash, err := json.Marshal(newEvent)
if err != nil {
return
}
err, newEvent.Hashes.SHA256 = utils.Hash(newEventBytesForHash)
if err != nil {
return
}
newEvent.Unsigned = UnsignedData{}
newEventBytesForSign, err := json.Marshal(newEvent)
if err != nil {
return
}
newEvent.Signatures = utils.SignContent(newEventBytesForSign)
newEvent.Unsigned = UnsignedData{
TransactionId: txnId,
}
return
}
func SendMessageHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := SendMessageRequest{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
token, errResponse := utils.GetAccessToken(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
foundUser, err := user.ReadUserFromAccessToken(token)
if err != nil || foundUser == nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "M_UNKNOWN_TOKEN", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
panic(err)
}
return
}
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
roomId := vars["roomId"]
eventType := vars["eventType"]
txnId := vars["txnId"]
if roomId == "" || eventType == "" || txnId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
content, _ := json.Marshal(request)
err, newEvent := New(
roomId,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
eventType,
foundUser.Id,
string(content),
txnId,
)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Creating Event: %s", err)}); err != nil {
panic(err)
}
return
}
err = CreateEvent(newEvent, txnId)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
transaction := &Transaction{
Id: txnId,
Origin: config.Homeserver,
Timestamp: time.Now().Unix(),
PDUS: []*Event{newEvent},
}
servers, err := ReadServers(roomId)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
for _, server := range servers {
if server != config.Homeserver {
log.Printf("Send Transaction to %s", server)
operation := func() error {
return SendTransaction(transaction, server, config.HttpString, config.AuthentificationCheck)
}
notify := func(err error, duration time.Duration) {
log.Printf("Error Sending Transaction, retrying in %ss: %s", duration/1000000000, err)
}
backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
}
}
response := createEventResponse{
EventId: newEvent.Id,
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
}
func CreateStateEventHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
token, errResponse := utils.GetAccessToken(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
foundUser, err := user.ReadUserFromAccessToken(token)
if err != nil || foundUser == nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "M_UNKNOWN_TOKEN", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
roomId := vars["roomId"]
eventType := vars["eventType"]
stateKey := vars["stateKey"]
if roomId == "" || eventType == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
content := buf.String()
err, newEvent := New(
roomId,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
eventType,
stateKey,
content,
"",
)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Creating Event: %s", err)}); err != nil {
panic(err)
}
return
}
err = CreateEvent(newEvent, "")
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
err, txnId := utils.CreateUUID()
transaction := &Transaction{
Id: txnId,
Origin: config.Homeserver,
Timestamp: time.Now().Unix(),
PDUS: []*Event{newEvent},
}
servers, err := ReadServers(roomId)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
for _, server := range servers {
operation := func() error {
return SendTransaction(transaction, server, config.HttpString, config.AuthentificationCheck)
}
notify := func(err error, duration time.Duration) {
log.Printf("Error Sending Transaction, retrying in %ss: %s", duration/1000000000, err)
}
go backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
}
response := createEventResponse{
EventId: newEvent.Id,
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
}
func GetEventUserHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := getEventRequest{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
token, errResponse := utils.GetAccessToken(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
foundUser, err := user.ReadUserFromAccessToken(token)
if err != nil || foundUser == nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "M_UNKNOWN_TOKEN", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
panic(err)
}
return
}
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
roomId := vars["roomId"]
eventId := vars["eventId"]
if roomId == "" || eventId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
foundEvent, err := ReadEvent(eventId)
if err != nil || foundEvent == nil {
w.WriteHeader(http.StatusNotFound)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "M_NOT_FOUND", ErrorMessage: fmt.Sprintf("Event not found. %s", err)}); err != nil {
panic(err)
}
return
}
response := getEventResponse{
Content: foundEvent.Content,
EventType: foundEvent.EventType,
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
}
func GetStateEventHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
token, errResponse := utils.GetAccessToken(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
foundUser, err := user.ReadUserFromAccessToken(token)
if err != nil || foundUser == nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "M_UNKNOWN_TOKEN", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
roomId := vars["roomId"]
eventType := vars["eventType"]
stateKey := vars["stateKey"]
if roomId == "" || eventType == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
foundEvent, err := ReadStateEvent(roomId, eventType, stateKey)
if err != nil || foundEvent == nil {
w.WriteHeader(http.StatusNotFound)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "M_NOT_FOUND", ErrorMessage: fmt.Sprintf("Event not found. %s", err)}); err != nil {
panic(err)
}
return
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(foundEvent.Content); err != nil {
panic(err)
}
}
func SyncEventsServerHandler(w http.ResponseWriter, r *http.Request) {
packetLossNumber := rand.Intn(100)
if packetLossNumber > config.Packetloss {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
request := syncEventsServerRequest{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
_ = utils.CheckAuthHeader(r, buf.String())
/*if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}*/
err := json.Unmarshal(buf.Bytes(), &request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("SyncEventsServerHandler Could not parse JSON Request: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
txnId := vars["txnId"]
if txnId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "SyncEventsServerHandler Missing Parameter"}); err != nil {
panic(err)
}
return
}
response := syncEventsServerResponse{
PDUs: make(map[string]pduProcessingResult),
}
missingEventIds := make(map[string][]string)
for _, pdu := range request.PDUs {
signatureValid := CheckSignature(*pdu)
if !signatureValid {
log.Printf("Wrong Signature for Event %s", pdu.Id)
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: "Signature not valid"}
//continue
}
authEventsValid, err := CheckAuthEvents(pdu)
if !authEventsValid || err != nil {
log.Printf("Wrong Auth Events for Event %s", pdu.Id)
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Error in Auth Check: %s", err)}
//continue
}
missingParentIds, err := CheckParents(pdu)
if len(missingParentIds) > 0 || err != nil {
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Error in Parents Check: %s", err)}
for _, parentId := range missingParentIds {
missingEventIds[pdu.RoomId] = append(missingEventIds[pdu.RoomId], parentId)
}
}
err = HandleEvent(pdu, txnId)
if err != nil {
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Error in Event-Handling: %s", err)}
continue
}
response.PDUs[pdu.Id] = pduProcessingResult{}
}
if len(missingEventIds) > 0 {
for roomId, eventIds := range missingEventIds {
Backfill(eventIds, roomId, request.Origin, config.HttpString, config.AuthentificationCheck)
}
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
} else {
log.Println("Blocking Response")
}
}
func BackfillHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
errResponse := utils.CheckAuthHeader(r, "")
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
roomId := vars["roomId"]
if roomId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
limit := 50
eventIds, ok := r.URL.Query()["v"]
if !ok || eventIds[0] == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
limitString := r.URL.Query().Get("limit")
if limitString != "" {
limit, _ = strconv.Atoi(limitString)
}
pdus := []*Event{}
for len(pdus) < limit {
newEventIds := []string{}
for _, eventId := range eventIds {
foundEvent, err := ReadEvent(eventId)
if err != nil || foundEvent == nil {
continue
}
for newEventId, _ := range foundEvent.PrevEventHashes {
newEventIds = append(newEventIds, newEventId)
}
pdus = append(pdus, foundEvent)
}
eventIds = newEventIds
}
response := backfillResponse{
Origin: config.Homeserver,
Timestamp: time.Now().Unix(),
PDUs: pdus,
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
}
func SendTransaction(transaction *Transaction, homeserver string, httpString string, authentification bool) (err error) {
requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/send/%s?", httpString, homeserver, transaction.Id)
request := syncEventsServerRequest{
Origin: transaction.Origin,
Timestamp: transaction.Timestamp,
PDUs: transaction.PDUS,
}
reqBody, err := json.Marshal(request)
if err != nil {
return
}
client := &http.Client{Timeout: 2 * time.Second}
req, err := http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
if authentification {
var authHeader string
authHeader, err = utils.CreateAuthHeader(http.MethodPut, requestUrl, homeserver, string(reqBody))
if err != nil {
return
}
req.Header["Authorization"] = []string{authHeader}
}
req.Header["Content-Type"] = []string{"application/json"}
r, err := client.Do(req)
if err != nil {
return
}
if r.StatusCode != http.StatusOK {
utils.HandleHTTPError(r)
} else {
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
content := buf.String()
if content == "" {
err = errors.New("Missing Response")
return
}
}
return
}
func Backfill(eventIds []string, roomId string, homeserver string, httpString string, authentification bool) (err error) {
requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/backfill/%s?", httpString, homeserver, roomId)
for _, eventId := range eventIds {
requestUrl = fmt.Sprintf("%sv=%s&", requestUrl, eventId)
}
client := &http.Client{Timeout: 2 * time.Second}
var req *http.Request
req, err = http.NewRequest(http.MethodGet, requestUrl, bytes.NewBuffer(nil))
if err != nil {
return
}
if authentification {
var authHeader string
authHeader, err = utils.CreateAuthHeader(http.MethodGet, requestUrl, homeserver, "")
if err != nil {
return
}
req.Header["Authorization"] = []string{authHeader}
}
req.Header["Content-Type"] = []string{"application/json"}
r, err := client.Do(req)
if err != nil {
return
}
if r.StatusCode != http.StatusOK {
errResponse := utils.HandleHTTPError(r)
log.Fatalf("%s (%s)", errResponse.ErrorMessage, errResponse.ErrorCode)
}
response := backfillResponse{}
defer r.Body.Close()
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&response)
if err != nil {
return
}
var missingEventIds []string
for _, pdu := range response.PDUs {
for i, eventId := range missingEventIds {
if pdu.Id == eventId {
missingEventIds = append(missingEventIds[:i], missingEventIds[i+1:]...)
}
}
signatureValid := CheckSignature(*pdu)
if !signatureValid {
log.Printf("Wrong Signature for Event %s", pdu.Id)
missingEventIds = append(missingEventIds, pdu.Id)
continue
}
authEventsValid, err := CheckAuthEvents(pdu)
if !authEventsValid || err != nil {
log.Printf("Wrong Auth Events for Event %s", pdu.Id)
missingEventIds = append(missingEventIds, pdu.Id)
}
missingParentIds, err := CheckParents(pdu)
if len(missingParentIds) > 0 || err != nil {
for _, parentId := range missingParentIds {
missingEventIds = append(missingEventIds, parentId)
}
}
err = HandleEvent(pdu, "")
if err != nil {
log.Printf("Error in Event-Handling: %s", err)
continue
}
}
if len(missingEventIds) > 0 {
Backfill(missingEventIds, roomId, homeserver, config.HttpString, config.AuthentificationCheck)
}
return
}
func generateEventId(id string) string {
return fmt.Sprintf("$%s:%s", id, config.Homeserver)
}
func GetAuthChain(newEvent *Event) (authChain []*Event, err error) {
if !config.AuthentificationCheck {
return
}
createEvent, err := ReadStateEvent(newEvent.RoomId, "m.room.create", "")
if err != nil {
return
}
if createEvent != nil {
authChain = append(authChain, createEvent)
}
powerLevelEvent, err := ReadStateEvent(newEvent.RoomId, "m.room.power_levels", "")
if err != nil {
return
}
if powerLevelEvent != nil {
authChain = append(authChain, powerLevelEvent)
}
stateKey := newEvent.Sender
if newEvent.EventType == "m.room.member" {
stateKey = newEvent.StateKey
}
memberEvent, err := ReadStateEvent(newEvent.RoomId, "m.room.member", stateKey)
if err != nil {
return
}
if memberEvent != nil {
authChain = append(authChain, memberEvent)
}
joinRuleEvent, err := ReadStateEvent(newEvent.RoomId, "m.room.join_rules", "")
if err != nil {
return
}
if joinRuleEvent != nil && newEvent.EventType == "m.room.member" {
authChain = append(authChain, joinRuleEvent)
}
return
}
func GetAuthEvents(newEvent *Event) (authEventHashes map[string]EventHash, err error) {
authEventHashes = make(map[string]EventHash)
authChain, err := GetAuthChain(newEvent)
if err != nil {
return
}
for _, authEvent := range authChain {
authEventHashes[authEvent.Id] = authEvent.Hashes
}
return
}
func CheckEventHash(id string, hash EventHash) (correct bool, eventFound bool, err error) {
foundEvent, err := ReadEvent(id)
correct = true
eventFound = true
if err != nil {
return
}
if foundEvent == nil {
eventFound = false
return
}
if hash.SHA256 != foundEvent.Hashes.SHA256 {
correct = false
return
}
return
}
func CheckParents(eventToCheck *Event) (missingParentIds []string, err error) {
if config.Consensus {
for key, hash := range eventToCheck.PrevEventHashes {
correctHash, foundEvent, err := CheckEventHash(key, hash)
if !correctHash || !foundEvent || err != nil {
missingParentIds = append(missingParentIds, key)
}
}
}
return
}
func CheckAuthEvents(eventToCheck *Event) (correct bool, err error) {
correct = true
if !config.AuthentificationCheck {
return
}
authEvents, err := GetAuthEvents(eventToCheck)
if err != nil {
return
}
for key, hash := range authEvents {
if eventToCheck.AuthEventHashes[key].SHA256 != hash.SHA256 {
//correct = false
return
}
}
return
}
func CheckSignature(eventToCheck Event) (correct bool) {
if !config.Signing {
correct = true
return
}
correct = false
signatures := eventToCheck.Signatures
eventToCheck.Unsigned = UnsignedData{}
eventToCheck.Signatures = nil
jsonString, err := json.Marshal(eventToCheck)
if err != nil {
return
}
for id, signature := range signatures[eventToCheck.Origin] {
verifyKey, err := device.GetVerifyKey(eventToCheck.Origin, id)
if err == nil && verifyKey != nil {
correct = utils.VerifySignature(verifyKey, jsonString, signature)
}
}
return
}
func HandleEvents(events []*Event, txnId string) (err error) {
for _, eventToHandle := range events {
err = HandleEvent(eventToHandle, txnId)
}
return
}
func HandleEvent(eventToHandle *Event, txnId string) (err error) {
log.Printf("EventType: %s", eventToHandle.EventType)
foundEvent, err := ReadEvent(eventToHandle.Id)
if foundEvent == nil && err == nil {
err = CreateEvent(eventToHandle, txnId)
}
if err != nil {
return
}
if eventToHandle.EventType == "m.room.message" {
log.Printf("%s: %s", eventToHandle.Sender, eventToHandle.Content)
} else if eventToHandle.EventType == "m.room.member" {
message := MemberEventContent{}
err = json.Unmarshal([]byte(eventToHandle.Content), &message)
if err != nil {
return
}
if message.Membership == "join" {
log.Printf("Join %s to Room %s", eventToHandle.StateKey, eventToHandle.RoomId)
}
err = CreateRoomMember(eventToHandle.RoomId, eventToHandle.StateKey, eventToHandle.Origin)
if err != nil {
return
}
}
return
}