Changes
This commit is contained in:
parent
7db9c374cc
commit
9eac960763
26 changed files with 3119 additions and 266 deletions
|
@ -1,13 +1,114 @@
|
|||
package room
|
||||
|
||||
import (
|
||||
"nutfactory.org/Matrix/entities/event"
|
||||
)
|
||||
import "nutfactory.org/Matrix/entities/event"
|
||||
|
||||
type Room struct {
|
||||
Id string `json:"id,omitempty"`
|
||||
Messages map[string]*event.Event `json:"messages,omitempty"`
|
||||
//State map[string]event.Event `json:"state,omitempty"`
|
||||
Members []string `json:"members,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Id string `json:"id,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Topic string `json:"topic,omitempty"`
|
||||
Members []string `json:"members,omitempty"`
|
||||
Servers []string
|
||||
Events map[string]*event.Event `json:"events,omitempty"`
|
||||
Visibility string `json:"visibility,omitempty"`
|
||||
IsDirect bool `json:"is_direct,omitempty"`
|
||||
Federated bool `json:"federated,omitempty"`
|
||||
}
|
||||
|
||||
type createRoomRequest struct {
|
||||
Visibility string `json:"visibility,omitempty"`
|
||||
RoomAliasName string `json:"room_alias_name,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Topic string `json:"topic,omitempty"`
|
||||
Invite string `json:"invite,omitempty"`
|
||||
Invite3pid invite3pid `json:"invite_3pid,omitempty"`
|
||||
RoomVersion string `json:"room_version,omitempty"`
|
||||
CreationContent creationContent `json:"creation_content,omitempty"`
|
||||
InitialState []event.StateEvent `json:"initial_state,omitempty"`
|
||||
Preset string `json:"preset,omitempty"`
|
||||
IsDirect bool `json:"is_direct,omitempty"`
|
||||
PowerLevelContentOverride string `json:"power_level_content_override,omitempty"`
|
||||
}
|
||||
|
||||
type createRoomResponse struct {
|
||||
RoomId string `json:"room_id,omitempty"`
|
||||
}
|
||||
|
||||
type getRoomMemberRequest struct{}
|
||||
|
||||
type getRoomMemberResponse struct {
|
||||
Chunk []*event.Event `json:"chunk,omitempty"`
|
||||
}
|
||||
|
||||
type joinRoomUserRequest struct {
|
||||
ThirdPartySigned thirdPartySigned `json:"third_party_signed,omitempty"`
|
||||
}
|
||||
|
||||
type joinRoomUserResponse struct {
|
||||
RoomId string `json:"room_id,omitempty"`
|
||||
}
|
||||
|
||||
type leaveRoomUserRequest struct{}
|
||||
|
||||
type leaveRoomUserResponse struct{}
|
||||
|
||||
type makeJoinRequest struct{}
|
||||
|
||||
type makeJoinResponse struct {
|
||||
RoomVersion string `json:"room_version,omitempty"`
|
||||
Event event.Event `json:"event,omitempty"`
|
||||
}
|
||||
|
||||
type joinRoomServerRequest struct {
|
||||
Sender string `json:"sender,omitempty"`
|
||||
Origin string `json:"origin,omitempty"`
|
||||
Timestamp int64 `json:"origin_server_ts,omitempty"`
|
||||
EventType string `json:"type,omitempty"`
|
||||
StateKey string `json:"state_key,omitempty"`
|
||||
Content event.MemberEventContent `json:"content,omitempty"`
|
||||
}
|
||||
|
||||
type joinRoomServerResponse struct {
|
||||
Origin string `json:"origin,omitempty"`
|
||||
AuthChain []*event.Event `json:"auth_chain,omitempty"`
|
||||
State []*event.Event `json:"state,omitempty"`
|
||||
}
|
||||
|
||||
type makeLeaveRequest struct{}
|
||||
|
||||
type makeLeaveResponse struct{}
|
||||
|
||||
type leaveRoomServerRequest struct{}
|
||||
|
||||
type leaveRoomServerResponse struct{}
|
||||
|
||||
type invite3pid struct {
|
||||
IdServer string `json:"id_server,omitempty"`
|
||||
IdAccessToken string `json:"id_access_token,omitempty"`
|
||||
Medium string `json:"medium,omitempty"`
|
||||
Address string `json:"address,omitempty"`
|
||||
}
|
||||
|
||||
type creationContent struct {
|
||||
Federated bool `json:"m.federate,omitempty"`
|
||||
}
|
||||
|
||||
type unsignedData struct {
|
||||
Age int `json:"age,omitempty"`
|
||||
RedactedBecause *event.Event `json:"redacted_because,omitempty"`
|
||||
TransactionId string `json:"transaction_id,omitempty"`
|
||||
}
|
||||
|
||||
type invite struct {
|
||||
DisplayName string `json:"display_name,omitempty"`
|
||||
Signed thirdPartySigned `json:"signed,omitempty"`
|
||||
}
|
||||
|
||||
type thirdPartySigned struct {
|
||||
Sender string `json:"sender,omitempty"`
|
||||
MXID string `json:"mxid,omitempty"`
|
||||
Signatures signatures `json:"signatures,omitempty"`
|
||||
Token string `json:"token,omitempty"`
|
||||
}
|
||||
|
||||
type signatures struct{}
|
||||
|
|
|
@ -1,5 +1,770 @@
|
|||
package room
|
||||
|
||||
func New() (room *Room) {
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"github.com/gorilla/mux"
|
||||
"nutfactory.org/Matrix/config"
|
||||
"nutfactory.org/Matrix/entities/event"
|
||||
"nutfactory.org/Matrix/entities/user"
|
||||
"nutfactory.org/Matrix/utils"
|
||||
)
|
||||
|
||||
func New(
|
||||
version string,
|
||||
name string,
|
||||
topic string,
|
||||
visibility string,
|
||||
isDirect bool,
|
||||
federated bool,
|
||||
creatorId string,
|
||||
) (err error, newRoom *Room) {
|
||||
err, roomId := utils.CreateUUID()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id := generateRoomId(roomId)
|
||||
newRoom = &Room{
|
||||
Id: id,
|
||||
Version: version,
|
||||
Name: name,
|
||||
Topic: topic,
|
||||
Members: []string{creatorId},
|
||||
Events: make(map[string]*event.Event),
|
||||
Visibility: visibility,
|
||||
IsDirect: isDirect,
|
||||
Federated: federated,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func CreateRoomHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
request := createRoomRequest{}
|
||||
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
|
||||
}
|
||||
|
||||
err, newRoom := New(
|
||||
request.RoomVersion,
|
||||
request.Name,
|
||||
request.Topic,
|
||||
request.Visibility,
|
||||
request.IsDirect,
|
||||
request.CreationContent.Federated,
|
||||
foundUser.Id,
|
||||
)
|
||||
err = CreateRoom(newRoom)
|
||||
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
|
||||
}
|
||||
createEventContent := event.CreateEventContent{
|
||||
Creator: foundUser.Id,
|
||||
Federated: request.CreationContent.Federated,
|
||||
RoomVersion: newRoom.Version,
|
||||
}
|
||||
createEventContentBytes, _ := json.Marshal(createEventContent)
|
||||
err, createEvent := event.New(
|
||||
newRoom.Id,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.create",
|
||||
"",
|
||||
string(createEventContentBytes),
|
||||
"",
|
||||
)
|
||||
if err == nil {
|
||||
err = event.CreateEvent(createEvent, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
memberEventContent := event.MemberEventContent{
|
||||
DisplayName: foundUser.Name,
|
||||
IsDirect: request.IsDirect,
|
||||
Membership: "join",
|
||||
}
|
||||
memberEventContentBytes, _ := json.Marshal(memberEventContent)
|
||||
err, memberEvent := event.New(
|
||||
newRoom.Id,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.member",
|
||||
foundUser.Id,
|
||||
string(memberEventContentBytes),
|
||||
"",
|
||||
)
|
||||
if err == nil {
|
||||
err = event.CreateEvent(memberEvent, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
userPowerLevel := make(map[string]int)
|
||||
userPowerLevel[foundUser.Id] = 100
|
||||
powerLevelEventContent := event.PowerLevelsEventContent{
|
||||
Ban: 50,
|
||||
EventsDefault: 0,
|
||||
Invite: 50,
|
||||
Kick: 50,
|
||||
Redact: 50,
|
||||
StateDefault: 50,
|
||||
Users: userPowerLevel,
|
||||
UsersDefault: 0,
|
||||
Notifications: event.Notifications{
|
||||
Room: 50,
|
||||
},
|
||||
}
|
||||
powerLevelEventContentBytes, _ := json.Marshal(powerLevelEventContent)
|
||||
err, powerLevelEvent := event.New(
|
||||
newRoom.Id,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.power_levels",
|
||||
"",
|
||||
string(powerLevelEventContentBytes),
|
||||
"",
|
||||
)
|
||||
if err == nil {
|
||||
err = event.CreateEvent(powerLevelEvent, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
joinRule := "invite"
|
||||
historyVisibilty := "shared"
|
||||
guestAccess := "can_join"
|
||||
if request.Preset == "public_chat" {
|
||||
joinRule = "public"
|
||||
guestAccess = "forbidden"
|
||||
}
|
||||
joinRuleEventContent := event.JoinRuleEventContent{
|
||||
JoinRule: joinRule,
|
||||
}
|
||||
joinRuleEventContentBytes, _ := json.Marshal(joinRuleEventContent)
|
||||
err, joinRulesEvent := event.New(
|
||||
newRoom.Id,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.join_rules",
|
||||
"",
|
||||
string(joinRuleEventContentBytes),
|
||||
"",
|
||||
)
|
||||
if err == nil {
|
||||
err = event.CreateEvent(joinRulesEvent, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
historyVisiblilityEventContent := event.HistoryVisibilityEventContent{
|
||||
HistoryVisibility: historyVisibilty,
|
||||
}
|
||||
historyVisiblilityContentBytes, _ := json.Marshal(historyVisiblilityEventContent)
|
||||
err, historyVisibilityEvent := event.New(
|
||||
newRoom.Id,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.history_visibility",
|
||||
"",
|
||||
string(historyVisiblilityContentBytes),
|
||||
"",
|
||||
)
|
||||
if err == nil {
|
||||
err = event.CreateEvent(historyVisibilityEvent, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
guestAccessEventContent := event.GuestAccessEventContent{
|
||||
GuestAccess: guestAccess,
|
||||
}
|
||||
guestAccessContentBytes, _ := json.Marshal(guestAccessEventContent)
|
||||
err, guestAccessEvent := event.New(
|
||||
newRoom.Id,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.guest_access",
|
||||
"",
|
||||
string(guestAccessContentBytes),
|
||||
"",
|
||||
)
|
||||
if err == nil {
|
||||
err = event.CreateEvent(guestAccessEvent, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
nameEventContent := event.NameEventContent{
|
||||
Name: newRoom.Name,
|
||||
}
|
||||
nameContentBytes, _ := json.Marshal(nameEventContent)
|
||||
err, nameEvent := event.New(
|
||||
newRoom.Id,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.name",
|
||||
"",
|
||||
string(nameContentBytes),
|
||||
"",
|
||||
)
|
||||
if err == nil {
|
||||
err = event.CreateEvent(nameEvent, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
topicEventContent := event.TopicEventContent{
|
||||
Topic: newRoom.Topic,
|
||||
}
|
||||
topicContentBytes, _ := json.Marshal(topicEventContent)
|
||||
err, topicEvent := event.New(
|
||||
newRoom.Id,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.topic",
|
||||
"",
|
||||
string(topicContentBytes),
|
||||
"",
|
||||
)
|
||||
if err == nil {
|
||||
err = event.CreateEvent(topicEvent, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
response := createRoomResponse{RoomId: newRoom.Id}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func GetRoomMemberHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
request := getRoomMemberRequest{}
|
||||
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"]
|
||||
if roomId == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Params"}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
event.ReadStateEvents(roomId, "m.room.member")
|
||||
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode("Not Implemented"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
request := joinRoomUserRequest{}
|
||||
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"]
|
||||
if roomId == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
foundRoom, err := ReadRoom(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
|
||||
}
|
||||
var joinEvent *event.Event
|
||||
if foundRoom == nil {
|
||||
memberEventContent := event.MemberEventContent{
|
||||
DisplayName: foundUser.Name,
|
||||
IsDirect: true,
|
||||
Membership: "join",
|
||||
}
|
||||
memberEventContentBytes, _ := json.Marshal(memberEventContent)
|
||||
err, memberEvent := event.New(
|
||||
roomId,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.member",
|
||||
foundUser.Id,
|
||||
string(memberEventContentBytes),
|
||||
"",
|
||||
)
|
||||
if err == nil {
|
||||
err = event.CreateEvent(memberEvent, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
httpString := "https"
|
||||
server := strings.Split(roomId, ":")[1]
|
||||
requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/make_join/%s/%s", httpString, server, roomId, foundUser.Id)
|
||||
res, err := http.Get(requestUrl)
|
||||
makeJoinRes := makeJoinResponse{}
|
||||
decoder = json.NewDecoder(res.Body)
|
||||
err = decoder.Decode(&makeJoinRes)
|
||||
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
|
||||
}
|
||||
err = CreateRoom(&Room{Id: roomId, Version: makeJoinRes.RoomVersion})
|
||||
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, joinEvent = event.New(
|
||||
roomId,
|
||||
makeJoinRes.Event.Sender,
|
||||
makeJoinRes.Event.Origin,
|
||||
makeJoinRes.Event.Timestamp,
|
||||
makeJoinRes.Event.EventType,
|
||||
makeJoinRes.Event.StateKey,
|
||||
makeJoinRes.Event.Content,
|
||||
"",
|
||||
)
|
||||
requestUrl = fmt.Sprintf("%s://%s/_matrix/federation/v2/send_join/%s/%s", httpString, server, roomId, joinEvent.Id)
|
||||
reqBody, err := json.Marshal(joinEvent)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res, err = client.Do(req)
|
||||
joinRes := joinRoomServerResponse{}
|
||||
decoder = json.NewDecoder(res.Body)
|
||||
err = decoder.Decode(&joinRes)
|
||||
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
|
||||
}
|
||||
err = event.HandleEvents(joinRes.State)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Handling Events: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
memberEventContent := event.MemberEventContent{
|
||||
DisplayName: foundUser.Name,
|
||||
IsDirect: true,
|
||||
Membership: "join",
|
||||
}
|
||||
memberEventContentBytes, _ := json.Marshal(memberEventContent)
|
||||
err, joinEvent = event.New(
|
||||
roomId,
|
||||
foundUser.Id,
|
||||
config.Homeserver,
|
||||
time.Now().Unix(),
|
||||
"m.room.member",
|
||||
foundUser.Id,
|
||||
string(memberEventContentBytes),
|
||||
"",
|
||||
)
|
||||
}
|
||||
err, txnId := utils.CreateUUID()
|
||||
err = event.CreateEvent(joinEvent, 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 := &event.Transaction{
|
||||
Id: txnId,
|
||||
Origin: config.Homeserver,
|
||||
Timestamp: time.Now().Unix(),
|
||||
PDUS: []*event.Event{joinEvent},
|
||||
}
|
||||
servers, err := event.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 {
|
||||
operation := func() error {
|
||||
return event.SendTransaction(transaction, server)
|
||||
}
|
||||
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)
|
||||
//}
|
||||
}
|
||||
err = CreateRoomMember(roomId, foundUser.Id)
|
||||
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
|
||||
}
|
||||
response := joinRoomUserResponse{RoomId: roomId}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
request := makeJoinRequest{}
|
||||
errResponse := utils.CheckRequest(r)
|
||||
if errResponse != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(errResponse); 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"]
|
||||
userId := vars["userId"]
|
||||
if roomId == "" || userId == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
homeserver := strings.Split(userId, ":")
|
||||
if len(homeserver) <= 1 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Homeserver in UserId"}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
foundRoom, err := ReadRoom(roomId)
|
||||
if err != nil || foundRoom == nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "MISSING_ROOM", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
memberEventContent := event.MemberEventContent{
|
||||
Membership: "join",
|
||||
}
|
||||
|
||||
memberEventContentBytes, err := json.Marshal(memberEventContent)
|
||||
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
|
||||
}
|
||||
|
||||
response := makeJoinResponse{
|
||||
RoomVersion: foundRoom.Version,
|
||||
Event: event.Event{
|
||||
Sender: userId,
|
||||
Origin: homeserver[1],
|
||||
Timestamp: time.Now().Unix(),
|
||||
EventType: "m.room.member",
|
||||
StateKey: userId,
|
||||
Content: string(memberEventContentBytes),
|
||||
},
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: TEST
|
||||
func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
request := event.Event{}
|
||||
errResponse := utils.CheckRequest(r)
|
||||
if errResponse != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(errResponse); 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
|
||||
}
|
||||
foundRoom, err := ReadRoom(roomId)
|
||||
if err != nil || foundRoom == nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "MISSING_ROOM", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
request.RoomId = roomId
|
||||
request.Id = eventId
|
||||
|
||||
memberEventContent := event.MemberEventContent{}
|
||||
err = json.Unmarshal([]byte(request.Content), &memberEventContent)
|
||||
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
|
||||
}
|
||||
if memberEventContent.Membership != "join" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Wrong Membership"}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
err = event.CreateEvent(&request, "")
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
CreateRoomMember(roomId, request.StateKey)
|
||||
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
|
||||
}
|
||||
authChain, err := event.GetAuthChain(&request)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Creating Auth Chain: %s", err)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
stateEvents, err := event.ReadStateEventsFromRoom(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
|
||||
}
|
||||
response := joinRoomServerResponse{
|
||||
Origin: config.Homeserver,
|
||||
AuthChain: authChain,
|
||||
State: stateEvents,
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func generateRoomId(id string) string {
|
||||
return fmt.Sprintf("!%s:%s", id, config.Homeserver)
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ import (
|
|||
"nutfactory.org/Matrix/utils/database"
|
||||
)
|
||||
|
||||
func CreateRoom(room *Room, userId string) (err error) {
|
||||
func CreateRoom(room *Room) (err error) {
|
||||
sqlStmt := fmt.Sprintf(`INSERT INTO room
|
||||
(id, version)
|
||||
(id, version, visibility, name, topic, isDirect, federated)
|
||||
VALUES
|
||||
(?, ?)`)
|
||||
(?, ?, ?, ?, ?, ?, ?)`)
|
||||
|
||||
tx, err := database.DB.Begin()
|
||||
if err != nil {
|
||||
|
@ -24,42 +24,31 @@ func CreateRoom(room *Room, userId string) (err error) {
|
|||
}
|
||||
defer stmt.Close()
|
||||
|
||||
_, err = stmt.Exec(room.Id, room.Version)
|
||||
_, err = stmt.Exec(
|
||||
room.Id,
|
||||
room.Version,
|
||||
room.Visibility,
|
||||
room.Name,
|
||||
room.Topic,
|
||||
room.IsDirect,
|
||||
room.Federated,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tx.Commit()
|
||||
err = CreateRoomMember(room.Id, userId)
|
||||
for _, userId := range room.Members {
|
||||
err = CreateRoomMember(room.Id, userId)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func CreateRoomMember(roomId string, userId string) (err error) {
|
||||
sqlStmt := fmt.Sprintf(`INSERT INTO roomMember
|
||||
(roomId, userId)
|
||||
VALUES
|
||||
(?, ?)`)
|
||||
|
||||
tx, err := database.DB.Begin()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
stmt, err := tx.Prepare(sqlStmt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
_, err = stmt.Exec(roomId, userId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tx.Commit()
|
||||
return
|
||||
return event.CreateRoomMember(roomId, userId)
|
||||
}
|
||||
|
||||
func ReadRoom(id string) (foundRoom *Room, err error) {
|
||||
queryStmt := fmt.Sprintf(`SELECT id, version
|
||||
queryStmt := fmt.Sprintf(`SELECT id, version, visibility, name, topic, isDirect, federated
|
||||
FROM room
|
||||
WHERE id = '%s'`, id)
|
||||
|
||||
|
@ -72,11 +61,19 @@ func ReadRoom(id string) (foundRoom *Room, err error) {
|
|||
|
||||
if rows.Next() {
|
||||
foundRoom = &Room{}
|
||||
err = rows.Scan(&foundRoom.Id, &foundRoom.Version)
|
||||
err = rows.Scan(
|
||||
&foundRoom.Id,
|
||||
&foundRoom.Version,
|
||||
&foundRoom.Visibility,
|
||||
&foundRoom.Name,
|
||||
&foundRoom.Topic,
|
||||
&foundRoom.IsDirect,
|
||||
&foundRoom.Federated,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
foundRoom.Messages, err = event.ReadEventsFromRoom(foundRoom.Id)
|
||||
foundRoom.Events, err = event.ReadEventsFromRoom(foundRoom.Id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -90,34 +87,17 @@ func ReadRoom(id string) (foundRoom *Room, err error) {
|
|||
}
|
||||
|
||||
func ReadRoomMembers(roomId string) (roomMembers []string, err error) {
|
||||
queryStmt := fmt.Sprintf(`SELECT userId
|
||||
FROM roomMember
|
||||
WHERE roomId = '%s'`, roomId)
|
||||
|
||||
rows, err := database.DB.Query(queryStmt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
roomMembers = []string{}
|
||||
|
||||
for rows.Next() {
|
||||
var foundUser string
|
||||
err = rows.Scan(&foundUser)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
roomMembers = append(roomMembers, foundUser)
|
||||
}
|
||||
|
||||
return
|
||||
return event.ReadRoomMembers(roomId)
|
||||
}
|
||||
|
||||
func UpdateRoom(room *Room) (err error) {
|
||||
sqlStmt := fmt.Sprintf(`UPDATE room SET
|
||||
version = ?
|
||||
version = ?,
|
||||
visibility = ?,
|
||||
name = ?,
|
||||
topic = ?,
|
||||
isDirect = ?,
|
||||
federated = ?
|
||||
WHERE id = ?`)
|
||||
|
||||
tx, err := database.DB.Begin()
|
||||
|
@ -131,7 +111,15 @@ func UpdateRoom(room *Room) (err error) {
|
|||
}
|
||||
defer stmt.Close()
|
||||
|
||||
_, err = stmt.Exec(room.Version, room.Id)
|
||||
_, err = stmt.Exec(
|
||||
room.Version,
|
||||
room.Visibility,
|
||||
room.Name,
|
||||
room.Topic,
|
||||
room.IsDirect,
|
||||
room.Federated,
|
||||
room.Id,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue