From c3b941841e193c1d5c32f9d6226a95475d627249 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Sun, 16 Feb 2020 23:27:03 +0100 Subject: [PATCH] Basic bridging going on both ways successfully --- appservice/account.go | 155 ++++++++++++------------------------------ appservice/db.go | 113 ++++++++++++++++++++++++++++++ appservice/server.go | 47 +++++++++++++ connector/irc/irc.go | 5 ++ main.go | 2 + 5 files changed, 212 insertions(+), 110 deletions(-) diff --git a/appservice/account.go b/appservice/account.go index 230860a..553165a 100644 --- a/appservice/account.go +++ b/appservice/account.go @@ -4,7 +4,6 @@ import ( "fmt" "log" - "git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib" . "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector" ) @@ -13,9 +12,52 @@ type Account struct { AccountName string Protocol string Conn Connector + + JoinedRooms map[RoomID]bool } +var registeredAccounts = map[string]map[string]*Account{} + +func AddAccount(a *Account) { + if _, ok := registeredAccounts[a.MatrixUser]; !ok { + registeredAccounts[a.MatrixUser] = make(map[string]*Account) + } + registeredAccounts[a.MatrixUser][a.AccountName] = a +} + +func FindAccount(mxUser string, name string) *Account { + if u, ok := registeredAccounts[mxUser]; ok { + if a, ok := u[name]; ok { + return a + } + } + return nil +} + +func FindJoinedAccount(mxUser string, protocol string, room RoomID) *Account { + if u, ok := registeredAccounts[mxUser]; ok { + for _, acct := range u { + if acct.Protocol == protocol { + if j, ok := acct.JoinedRooms[room]; ok && j { + return acct + } + } + } + } + return nil +} + +func RemoveAccount(mxUser string, name string) { + if u, ok := registeredAccounts[mxUser]; ok { + delete(u, name) + } +} + +// ---- + func (a *Account) Joined(roomId RoomID) { + a.JoinedRooms[roomId] = true + mx_room_id, err := dbGetMxRoom(a.Protocol, roomId) if err != nil { return @@ -30,6 +72,8 @@ func (a *Account) Joined(roomId RoomID) { } func (a *Account) Left(roomId RoomID) { + delete(a.JoinedRooms, roomId) + mx_room_id, err := dbGetMxRoom(a.Protocol, roomId) if err != nil { return @@ -112,112 +156,3 @@ func (a *Account) Event(event *Event) { } } -// ---- - -func dbGetMxRoom(protocol string, roomId RoomID) (string, error) { - var room DbRoomMap - - // Check if room exists in our mapping, - // If not create it - must_create := db.First(&room, DbRoomMap{ - Protocol: protocol, - RoomID: roomId, - }).RecordNotFound() - if must_create { - alias := roomAlias(protocol, roomId) - // Lookup alias - mx_room_id, err := mxDirectoryRoom(fmt.Sprintf("#%s:%s", alias, config.MatrixDomain)) - - // If no alias found, create room - if err != nil { - name := fmt.Sprintf("%s (%s)", roomId, protocol) - - mx_room_id, err = mxCreateRoom(name, alias, []string{}) - if err != nil { - log.Printf("Could not create room for %s: %s", name, err) - return "", err - } - } - - room = DbRoomMap{ - Protocol: protocol, - RoomID: roomId, - MxRoomID: mx_room_id, - } - db.Create(&room) - } - log.Printf("Got room id: %s", room.MxRoomID) - - 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 - - must_create := db.First(&user, DbUserMap{ - Protocol: protocol, - UserID: userId, - }).RecordNotFound() - if must_create { - username := userMxId(protocol, userId) - - err := mxRegisterUser(username) - if err != nil { - if mxE, ok := err.(*mxlib.MxError); !ok || mxE.ErrCode != "M_USER_IN_USE" { - log.Printf("Could not register %s: %s", username, err) - return "", err - } - } - - mxid := fmt.Sprintf("@%s:%s", username, config.MatrixDomain) - mxProfileDisplayname(mxid, fmt.Sprintf("%s (%s)", userId, protocol)) - - user = DbUserMap{ - Protocol: protocol, - UserID: userId, - MxUserID: mxid, - } - db.Create(&user) - } - - return user.MxUserID, nil -} - diff --git a/appservice/db.go b/appservice/db.go index c2af428..fad78ba 100644 --- a/appservice/db.go +++ b/appservice/db.go @@ -1,7 +1,12 @@ package appservice import ( + "fmt" + "log" + + "git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib" "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector" + "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" _ "github.com/jinzhu/gorm/dialects/postgres" @@ -69,3 +74,111 @@ type DbPmRoomMap struct { MxRoomID string `gorm:"index:mxroomoid"` } +// ---- + +func dbGetMxRoom(protocol string, roomId connector.RoomID) (string, error) { + var room DbRoomMap + + // Check if room exists in our mapping, + // If not create it + must_create := db.First(&room, DbRoomMap{ + Protocol: protocol, + RoomID: roomId, + }).RecordNotFound() + if must_create { + alias := roomAlias(protocol, roomId) + // Lookup alias + mx_room_id, err := mxDirectoryRoom(fmt.Sprintf("#%s:%s", alias, config.MatrixDomain)) + + // If no alias found, create room + if err != nil { + name := fmt.Sprintf("%s (%s)", roomId, protocol) + + mx_room_id, err = mxCreateRoom(name, alias, []string{}) + if err != nil { + log.Printf("Could not create room for %s: %s", name, err) + return "", err + } + } + + room = DbRoomMap{ + Protocol: protocol, + RoomID: roomId, + MxRoomID: mx_room_id, + } + db.Create(&room) + } + log.Printf("Got room id: %s", room.MxRoomID) + + return room.MxRoomID, nil +} + +func dbGetMxPmRoom(protocol string, them connector.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 connector.UserID) (string, error) { + var user DbUserMap + + must_create := db.First(&user, DbUserMap{ + Protocol: protocol, + UserID: userId, + }).RecordNotFound() + if must_create { + username := userMxId(protocol, userId) + + err := mxRegisterUser(username) + if err != nil { + if mxE, ok := err.(*mxlib.MxError); !ok || mxE.ErrCode != "M_USER_IN_USE" { + log.Printf("Could not register %s: %s", username, err) + return "", err + } + } + + mxid := fmt.Sprintf("@%s:%s", username, config.MatrixDomain) + mxProfileDisplayname(mxid, fmt.Sprintf("%s (%s)", userId, protocol)) + + user = DbUserMap{ + Protocol: protocol, + UserID: userId, + MxUserID: mxid, + } + db.Create(&user) + } + + return user.MxUserID, nil +} diff --git a/appservice/server.go b/appservice/server.go index 3f52119..ed206ee 100644 --- a/appservice/server.go +++ b/appservice/server.go @@ -8,6 +8,7 @@ import ( "net/http" "git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib" + "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector" "github.com/gorilla/mux" ) @@ -72,8 +73,54 @@ func handleTxn(w http.ResponseWriter, r *http.Request) { } log.Printf("Got transaction %#v\n", txn) + + for i := range txn.Events { + handleTxnEvent(&txn.Events[i]) + } + fmt.Fprintf(w, "{}\n") } else { http.Error(w, "Expected PUT request", http.StatusBadRequest) } } + +func handleTxnEvent(e *mxlib.Event) { + if e.Type == "m.room.message" { + ev := &connector.Event{ + Type: connector.EVENT_MESSAGE, + Text: e.Content["body"].(string), + } + typ := e.Content["msgtype"].(string) + if typ == "m.emote" { + ev.Type = connector.EVENT_MESSAGE + } + + // Look up if this is a private message room + var pm_room DbPmRoomMap + is_pm_room := !db.First(&pm_room, DbPmRoomMap{ + MxRoomID: e.RoomId, + }).RecordNotFound() + if is_pm_room { + acct := FindAccount(pm_room.MxUserID, pm_room.AccountName) + if acct != nil && e.Sender == pm_room.MxUserID { + ev.Author = acct.Conn.User() + ev.Recipient = pm_room.UserID + acct.Conn.Send(ev) + } + } + + // Look up if this is a regular room + var room DbRoomMap + is_room := !db.First(&room, DbRoomMap{ + MxRoomID: e.RoomId, + }).RecordNotFound() + if is_room { + acct := FindJoinedAccount(e.Sender, room.Protocol, room.RoomID) + if acct != nil { + ev.Author = acct.Conn.User() + ev.Room = room.RoomID + acct.Conn.Send(ev) + } + } + } +} diff --git a/connector/irc/irc.go b/connector/irc/irc.go index e57d71b..77359d0 100644 --- a/connector/irc/irc.go +++ b/connector/irc/irc.go @@ -170,6 +170,11 @@ func (irc *IRC) Leave(roomId RoomID) { } func (irc *IRC) Send(event *Event) error { + // Workaround girc bug + if event.Text[0] == ':' { + event.Text = " " + event.Text + } + dest := "" if event.Room != "" { ch, err := irc.checkRoomId(event.Room) diff --git a/main.go b/main.go index 0f8f3f0..eeff01e 100644 --- a/main.go +++ b/main.go @@ -188,8 +188,10 @@ func main() { AccountName: name, Protocol: params.Protocol, Conn: conn, + JoinedRooms: map[connector.RoomID]bool{}, } conn.SetHandler(account) + appservice.AddAccount(account) go connectAndJoin(conn, params) } }