diff options
-rw-r--r-- | appservice/account.go | 65 | ||||
-rw-r--r-- | appservice/db.go | 2 | ||||
-rw-r--r-- | appservice/matrix.go | 31 | ||||
-rw-r--r-- | appservice/server.go | 21 | ||||
-rw-r--r-- | mxlib/api.go | 16 |
5 files changed, 112 insertions, 23 deletions
diff --git a/appservice/account.go b/appservice/account.go index 4316362..230860a 100644 --- a/appservice/account.go +++ b/appservice/account.go @@ -84,23 +84,32 @@ func (a *Account) Event(event *Event) { if err != nil { log.Printf("Could not leave %s as %s", a.MatrixUser, mx_room_id) } - } else if event.Type == EVENT_MESSAGE { + } else { + log.Printf("%s msg %s %s", a.Protocol, event.Author, event.Room) + mx_room_id := "" + if len(event.Room) > 0 { - log.Printf("%s msg %s %s", a.Protocol, event.Author, event.Room) - mx_room_id, err := dbGetMxRoom(a.Protocol, event.Room) + mx_room_id, err = dbGetMxRoom(a.Protocol, event.Room) if err != nil { return } - - err = mxSendMessageAs(mx_room_id, event.Text, mx_user_id) + } else { + mx_room_id, err = dbGetMxPmRoom(a.Protocol, event.Author, mx_user_id, a.MatrixUser, a.AccountName) if err != nil { - log.Printf("Could not send %s as %s", event.Text, mx_user_id) + return } - } else { - // TODO + } + + typ := "m.text" + if event.Type == EVENT_ACTION { + typ = "m.emote" + } + + err = mxSendMessageAs(mx_room_id, typ, event.Text, mx_user_id) + if err != nil { + log.Printf("Could not send %s as %s", event.Text, mx_user_id) } } - // TODO } // ---- @@ -142,6 +151,44 @@ func dbGetMxRoom(protocol string, roomId RoomID) (string, error) { return room.MxRoomID, nil } +func dbGetMxPmRoom(protocol string, them UserID, themMxId string, usMxId string, usAccount string) (string, error) { + var room DbPmRoomMap + + must_create := db.First(&room, DbPmRoomMap{ + MxUserID: usMxId, + Protocol: protocol, + AccountName: usAccount, + UserID: them, + }).RecordNotFound() + if must_create { + name := fmt.Sprintf("%s (%s)", them, protocol) + + mx_room_id, err := mxCreateDirectRoomAs(name, []string{usMxId}, themMxId) + if err != nil { + log.Printf("Could not create room for %s: %s", name, err) + return "", err + } + + err = mxRoomJoinAs(mx_room_id, themMxId) + if err != nil { + log.Printf("Could not join %s as %s", mx_room_id, themMxId) + return "", err + } + + room = DbPmRoomMap{ + MxUserID: usMxId, + Protocol: protocol, + AccountName: usAccount, + UserID: them, + MxRoomID: mx_room_id, + } + db.Create(&room) + } + log.Printf("Got PM room id: %s", room.MxRoomID) + + return room.MxRoomID, nil +} + func dbGetMxUser(protocol string, userId UserID) (string, error) { var user DbUserMap diff --git a/appservice/db.go b/appservice/db.go index f8cbccf..c2af428 100644 --- a/appservice/db.go +++ b/appservice/db.go @@ -63,7 +63,7 @@ type DbPmRoomMap struct { AccountName string // User id to reach them - UserID connector.RoomID + UserID connector.UserID // Bridged room for PMs MxRoomID string `gorm:"index:mxroomoid"` diff --git a/appservice/matrix.go b/appservice/matrix.go index 96f643a..c85861d 100644 --- a/appservice/matrix.go +++ b/appservice/matrix.go @@ -135,6 +135,9 @@ func mxCreateRoom(name string, alias string, invite []string) (string, error) { CreationContent: map[string]interface{} { "m.federate": false, }, + PowerLevels: map[string]interface{} { + "invite": 100, + }, } var rep CreateRoomResponse err := mxPostApiCall("/_matrix/client/r0/createRoom", &rq, &rep) @@ -144,6 +147,28 @@ func mxCreateRoom(name string, alias string, invite []string) (string, error) { 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, @@ -177,10 +202,10 @@ func mxRoomLeaveAs(room string, user string) error { return err } -func mxSendMessageAs(room string, body string, user string) error { +func mxSendMessageAs(room string, typ string, body string, user string) error { txn_id := time.Now().UnixNano() - rq := RoomSendRequest{ - MsgType: "m.text", + rq := RoomSendMessageRequest{ + MsgType: typ, Body: body, } var rep RoomSendResponse diff --git a/appservice/server.go b/appservice/server.go index 8e4c263..3f52119 100644 --- a/appservice/server.go +++ b/appservice/server.go @@ -62,13 +62,18 @@ func checkTokenAndLog(handler http.Handler) http.Handler { } func handleTxn(w http.ResponseWriter, r *http.Request) { - var txn mxlib.Transaction - err := json.NewDecoder(r.Body).Decode(&txn) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - } - - log.Printf("Got transaction %#v\n", txn) + if r.Method == "PUT" { + var txn mxlib.Transaction + err := json.NewDecoder(r.Body).Decode(&txn) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + log.Printf("JSON decode error: %s\n", err) + return + } - fmt.Fprintf(w, "{}\n") + log.Printf("Got transaction %#v\n", txn) + fmt.Fprintf(w, "{}\n") + } else { + http.Error(w, "Expected PUT request", http.StatusBadRequest) + } } diff --git a/mxlib/api.go b/mxlib/api.go index cb2d10c..84c125b 100644 --- a/mxlib/api.go +++ b/mxlib/api.go @@ -18,7 +18,7 @@ type Transaction struct { } type Event struct { - Content map[string]string `json:"content"` + Content map[string]interface{} `json:"content"` Type string `json:"type"` EventId string `json:"event_id"` RoomId string `json:"room_id"` @@ -47,6 +47,17 @@ type CreateRoomRequest struct { Topic string `json:"topic"` Invite []string `json:"invite"` CreationContent map[string]interface{} `json:"creation_content"` + PowerLevels map[string]interface{} `json:"power_level_content_override"` +} + +type CreateRoomNoAliasRequest struct { + Preset string `json:"preset"` + Name string `json:"name"` + Topic string `json:"topic"` + Invite []string `json:"invite"` + CreationContent map[string]interface{} `json:"creation_content"` + PowerLevels map[string]interface{} `json:"power_level_content_override"` + IsDirect bool `json:"is_direct"` } type CreateRoomResponse struct { @@ -70,10 +81,11 @@ type RoomJoinResponse struct { RoomId string `json:"room_id"` } -type RoomSendRequest struct { +type RoomSendMessageRequest struct { MsgType string `json:"msgtype"` Body string `json:"body"` } type RoomSendResponse struct { EventId string `json:"event_id"` } + |