From c1f8d264f4fc297a0f8c5b8dffd64920499be9c8 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 19 Aug 2018 18:21:38 +0300 Subject: [PATCH] Fix portal DB scanning and add initial message bridging --- database/portal.go | 2 +- matrix.go | 2 +- portal.go | 81 ++++++++++++++++++++++++++++++++++++++++++++-- puppet.go | 12 +++++++ user.go | 55 ++++++++----------------------- 5 files changed, 106 insertions(+), 46 deletions(-) diff --git a/database/portal.go b/database/portal.go index 766e64d..68c8f39 100644 --- a/database/portal.go +++ b/database/portal.go @@ -87,7 +87,7 @@ type Portal struct { } func (portal *Portal) Scan(row Scannable) *Portal { - err := row.Scan(&portal.JID, &portal.MXID, &portal.Owner) + err := row.Scan(&portal.JID, &portal.Owner, &portal.MXID) if err != nil { if err != sql.ErrNoRows { portal.log.Fatalln("Database scan failed:", err) diff --git a/matrix.go b/matrix.go index e21ceda..78beccc 100644 --- a/matrix.go +++ b/matrix.go @@ -112,6 +112,6 @@ func (mx *MatrixHandler) HandleMessage(evt *gomatrix.Event) { portal := user.GetPortalByMXID(roomID) if portal != nil { - portal.HandleMessage(evt) + portal.HandleMatrixMessage(evt) } } diff --git a/portal.go b/portal.go index 2dfc5e0..9bf6bba 100644 --- a/portal.go +++ b/portal.go @@ -24,6 +24,7 @@ import ( "maunium.net/go/gomatrix" "strings" "maunium.net/go/mautrix-appservice" + "github.com/Rhymen/go-whatsapp" ) func (user *User) GetPortalByMXID(mxid types.MatrixRoomID) *Portal { @@ -95,6 +96,29 @@ type Portal struct { log log.Logger } +func (portal *Portal) Sync(contact whatsapp.Contact) { + + if len(portal.MXID) == 0 { + if !portal.IsPrivateChat() { + portal.Name = contact.Name + } + err := portal.CreateMatrixRoom() + if err != nil { + portal.log.Errorln("Failed to create portal room:", err) + return + } + } + + if !portal.IsPrivateChat() && portal.Name != contact.Name { + portal.Name = contact.Name + portal.Update() + // TODO add SetRoomName function to intent API + portal.MainIntent().SendStateEvent(portal.MXID, "m.room.name", "", map[string]interface{}{ + "name": portal.Name, + }) + } +} + func (portal *Portal) CreateMatrixRoom() error { if len(portal.MXID) > 0 { return nil @@ -136,6 +160,59 @@ func (portal *Portal) MainIntent() *appservice.IntentAPI { return portal.bridge.AppService.BotIntent() } -func (portal *Portal) HandleMessage(evt *gomatrix.Event) { - portal.log.Debugln("Received event:", evt) +func (portal *Portal) HandleTextMessage(message whatsapp.TextMessage) { + portal.CreateMatrixRoom() + var intent *appservice.IntentAPI + if portal.IsPrivateChat() { + intent = portal.MainIntent() + } else { + portal.log.Debugln("Received group text message:", message) + return + } + resp, err := intent.SendText(portal.MXID, message.Text) + portal.log.Debugln("Handled message ", message, "->", resp, err) +} + +func (portal *Portal) HandleMediaMessage(download func() ([]byte, error), msgID, mime, caption string) { + portal.CreateMatrixRoom() + var intent *appservice.IntentAPI + if portal.IsPrivateChat() { + intent = portal.MainIntent() + } else { + portal.log.Debugln("Received group media message:", msgID) + return + } + img, err := download() + if err != nil { + portal.log.Errorln("Failed to download media:", err) + return + } + uploaded, err := intent.UploadBytes(img, mime) + if err != nil { + portal.log.Errorln("Failed to upload media:", err) + return + } + resp, err := intent.SendImage(portal.MXID, caption, uploaded.ContentURI) + portal.log.Debugln("Handled message ", msgID, "->", resp, err) +} + +func (portal *Portal) HandleMatrixMessage(evt *gomatrix.Event) { + var err error + switch evt.Content.MsgType { + case gomatrix.MsgText: + err = portal.user.Conn.Send(whatsapp.TextMessage{ + Text: evt.Content.Body, + Info: whatsapp.MessageInfo{ + RemoteJid: portal.JID, + }, + }) + default: + portal.log.Debugln("Unhandled Matrix event:", evt) + return + } + if err != nil { + portal.log.Errorln("Error handling Matrix event %s: %v", evt.ID, err) + } else { + portal.log.Debugln("Handled Matrix event:", evt) + } } diff --git a/puppet.go b/puppet.go index 0d15975..7b31d9f 100644 --- a/puppet.go +++ b/puppet.go @@ -24,6 +24,7 @@ import ( "maunium.net/go/mautrix-whatsapp/types" "strings" "maunium.net/go/mautrix-appservice" + "github.com/Rhymen/go-whatsapp" ) const puppetJIDStrippedSuffix = "@s.whatsapp.net" @@ -132,3 +133,14 @@ type Puppet struct { func (puppet *Puppet) Intent() *appservice.IntentAPI { return puppet.bridge.AppService.Intent(puppet.MXID) } + +func (puppet *Puppet) Sync(contact whatsapp.Contact) { + puppet.Intent().EnsureRegistered() + + newName := puppet.bridge.Config.Bridge.FormatDisplayname(contact) + if puppet.Displayname != newName { + puppet.Displayname = newName + puppet.Update() + puppet.Intent().SetDisplayName(puppet.Displayname) + } +} diff --git a/user.go b/user.go index f34e5d8..b7d6da5 100644 --- a/user.go +++ b/user.go @@ -179,43 +179,6 @@ func (user *User) Login(roomID types.MatrixRoomID) { go user.Sync() } -func (user *User) SyncPuppet(contact whatsapp.Contact) { - puppet := user.GetPuppetByJID(contact.Jid) - puppet.Intent().EnsureRegistered() - - newName := user.bridge.Config.Bridge.FormatDisplayname(contact) - puppet.log.Debugln(puppet.Displayname, newName, contact.Name) - if puppet.Displayname != newName { - puppet.Displayname = newName - puppet.Update() - puppet.Intent().SetDisplayName(puppet.Displayname) - } -} - -func (user *User) SyncPortal(contact whatsapp.Contact) { - portal := user.GetPortalByJID(contact.Jid) - - if len(portal.MXID) == 0 { - if !portal.IsPrivateChat() { - portal.Name = contact.Name - } - err := portal.CreateMatrixRoom() - if err != nil { - user.log.Errorln("Failed to create portal:", err) - return - } - } - - if !portal.IsPrivateChat() && portal.Name != contact.Name { - portal.Name = contact.Name - portal.Update() - // TODO add SetRoomName function to intent API - portal.MainIntent().SendStateEvent(portal.MXID, "m.room.name", "", map[string]interface{}{ - "name": portal.Name, - }) - } -} - func (user *User) Sync() { user.log.Debugln("Syncing...") user.Conn.Contacts() @@ -224,7 +187,8 @@ func (user *User) Sync() { dat, _ := json.Marshal(&contact) user.log.Debugln(string(dat)) if strings.HasSuffix(jid, puppetJIDStrippedSuffix) { - user.SyncPuppet(contact) + puppet := user.GetPuppetByJID(contact.Jid) + puppet.Sync(contact) } if len(contact.Notify) == 0 && !strings.HasSuffix(jid, "@g.us") { @@ -232,7 +196,8 @@ func (user *User) Sync() { continue } - user.SyncPortal(contact) + portal := user.GetPortalByJID(contact.Jid) + portal.Sync(contact) } } @@ -241,15 +206,21 @@ func (user *User) HandleError(err error) { } func (user *User) HandleTextMessage(message whatsapp.TextMessage) { - user.log.Debugln("Text message:", message) + user.log.Debugln("Received text message:", message) + portal := user.GetPortalByJID(message.Info.RemoteJid) + portal.HandleTextMessage(message) } func (user *User) HandleImageMessage(message whatsapp.ImageMessage) { - user.log.Debugln("Image message:", message) + user.log.Debugln("Received image message:", message) + portal := user.GetPortalByJID(message.Info.RemoteJid) + portal.HandleMediaMessage(message.Download, message.Info.Id, message.Type, message.Caption) } func (user *User) HandleVideoMessage(message whatsapp.VideoMessage) { - user.log.Debugln("Video message:", message) + user.log.Debugln("Received video message:", message) + portal := user.GetPortalByJID(message.Info.RemoteJid) + portal.HandleMediaMessage(message.Download, message.Info.Id, message.Type, message.Caption) } func (user *User) HandleJsonMessage(message string) {