From fc4098d3e434c99203a36919b61f5afb17b6f7cb Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 4 Oct 2019 20:01:53 +0200 Subject: [PATCH] Receive stickers from whatsapp We need to convert them to png, otherwise synapse has trouble thumbnailing them. Also the default webp decoder can't decode WhatsApp stickers, so we use the chai2010 decoder. --- go.mod | 3 ++- go.sum | 4 ++++ portal.go | 43 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index b6cbceb..7a3ee86 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.11 require ( github.com/Rhymen/go-whatsapp v0.0.2-0.20190524185555-8d76e32a6d8e + github.com/chai2010/webp v1.1.0 github.com/lib/pq v1.1.1 github.com/mattn/go-sqlite3 v1.10.0 github.com/pkg/errors v0.8.1 @@ -16,6 +17,6 @@ require ( ) replace ( - github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.0.2-0.20190903182221-4e1a838ff3ba + github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.0.2-0.20191004160943-faf0ee6fab98 gopkg.in/russross/blackfriday.v2 => github.com/russross/blackfriday/v2 v2.0.1 ) diff --git a/go.sum b/go.sum index 0e4e7db..8cdfe7b 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk= github.com/Rhymen/go-whatsapp v0.0.0/go.mod h1:rdQr95g2C1xcOfM7QGOhza58HeI3I+tZ/bbluv7VazA= github.com/Rhymen/go-whatsapp v0.0.2-0.20190524185555-8d76e32a6d8e/go.mod h1:qf/2PQi82Okxw/igghu/oMGzTeUYuKBq1JNo3tdQyNg= +github.com/chai2010/webp v1.1.0 h1:4Ei0/BRroMF9FaXDG2e4OxwFcuW2vcXd+A6tyqTJUQQ= +github.com/chai2010/webp v1.1.0/go.mod h1:LP12PG5IFmLGHUU26tBiCBKnghxx3toZFwDjOYvd3Ow= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -43,6 +45,8 @@ github.com/tulir/go-whatsapp v0.0.2-0.20190830212741-33ca6ee47cf5 h1:0pUczFGOo4s github.com/tulir/go-whatsapp v0.0.2-0.20190830212741-33ca6ee47cf5/go.mod h1:u3Hdptbz3iB5y/NEoSKgsp9hBzUlm0A5OrLMVdENAX8= github.com/tulir/go-whatsapp v0.0.2-0.20190903182221-4e1a838ff3ba h1:exEcedSHn0qEZ1iwNwFF5brEuflhMScjFyyzmxUA+og= github.com/tulir/go-whatsapp v0.0.2-0.20190903182221-4e1a838ff3ba/go.mod h1:u3Hdptbz3iB5y/NEoSKgsp9hBzUlm0A5OrLMVdENAX8= +github.com/tulir/go-whatsapp v0.0.2-0.20191004160943-faf0ee6fab98 h1:TkKWIdhqxRBM8bZaJvp1q+awGJcY1f76zmlH7nHPDR8= +github.com/tulir/go-whatsapp v0.0.2-0.20191004160943-faf0ee6fab98/go.mod h1:u3Hdptbz3iB5y/NEoSKgsp9hBzUlm0A5OrLMVdENAX8= golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/portal.go b/portal.go index 6f2363a..15c4c17 100644 --- a/portal.go +++ b/portal.go @@ -33,6 +33,8 @@ import ( "sync" "time" + "github.com/chai2010/webp" + "github.com/Rhymen/go-whatsapp" waProto "github.com/Rhymen/go-whatsapp/binary/proto" "maunium.net/go/mautrix/format" @@ -189,13 +191,15 @@ func (portal *Portal) handleMessage(msg PortalMessage) { case whatsapp.TextMessage: portal.HandleTextMessage(msg.source, data) case whatsapp.ImageMessage: - portal.HandleMediaMessage(msg.source, data.Download, data.Thumbnail, data.Info, data.Type, data.Caption) + portal.HandleMediaMessage(msg.source, data.Download, data.Thumbnail, data.Info, data.Type, data.Caption, false) + case whatsapp.StickerMessage: + portal.HandleMediaMessage(msg.source, data.Download, data.Thumbnail, data.Info, data.Type, "", true) case whatsapp.VideoMessage: - portal.HandleMediaMessage(msg.source, data.Download, data.Thumbnail, data.Info, data.Type, data.Caption) + portal.HandleMediaMessage(msg.source, data.Download, data.Thumbnail, data.Info, data.Type, data.Caption, false) case whatsapp.AudioMessage: - portal.HandleMediaMessage(msg.source, data.Download, nil, data.Info, data.Type, "") + portal.HandleMediaMessage(msg.source, data.Download, nil, data.Info, data.Type, "", false) case whatsapp.DocumentMessage: - portal.HandleMediaMessage(msg.source, data.Download, data.Thumbnail, data.Info, data.Type, data.Title) + portal.HandleMediaMessage(msg.source, data.Download, data.Thumbnail, data.Info, data.Type, data.Title, false) case whatsappExt.MessageRevocation: portal.HandleMessageRevoke(msg.source, data) case FakeMessage: @@ -898,7 +902,7 @@ func (portal *Portal) HandleTextMessage(source *User, message whatsapp.TextMessa portal.finishHandling(source, message.Info.Source, resp.EventID) } -func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte, error), thumbnail []byte, info whatsapp.MessageInfo, mimeType, caption string) { +func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte, error), thumbnail []byte, info whatsapp.MessageInfo, mimeType, caption string, sendAsSticker bool) { if !portal.startHandling(info) { return } @@ -924,6 +928,25 @@ func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte, if detected := http.DetectContentType(data); detected != "application/octet-stream" { mimeType = detected } + + // synapse doesn't handle webp well, so we convert it. This can be dropped once https://github.com/matrix-org/synapse/issues/4382 is fixed + if mimeType == "image/webp" { + img, err := webp.Decode(bytes.NewReader(data)) + if err != nil { + portal.log.Errorfln("Failed to decode media for %s: %v", err) + return + } + + var buf bytes.Buffer + err = png.Encode(&buf, img) + if err != nil { + portal.log.Errorfln("Failed to convert media for %s: %v", err) + return + } + data = buf.Bytes() + mimeType = "image/png" + } + uploaded, err := intent.UploadBytes(data, mimeType) if err != nil { portal.log.Errorfln("Failed to upload media for %s: %v", err) @@ -963,7 +986,9 @@ func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte, switch strings.ToLower(strings.Split(mimeType, "/")[0]) { case "image": - content.MsgType = mautrix.MsgImage + if (!sendAsSticker) { + content.MsgType = mautrix.MsgImage + } cfg, _, _ := image.DecodeConfig(bytes.NewReader(data)) content.Info.Width = cfg.Width content.Info.Height = cfg.Height @@ -977,7 +1002,11 @@ func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte, _, _ = intent.UserTyping(portal.MXID, false, 0) ts := int64(info.Timestamp * 1000) - resp, err := intent.SendMassagedMessageEvent(portal.MXID, mautrix.EventMessage, &MessageContent{content, intent.IsCustomPuppet}, ts) + eventType := mautrix.EventMessage + if sendAsSticker { + eventType = mautrix.EventSticker + } + resp, err := intent.SendMassagedMessageEvent(portal.MXID, eventType, &MessageContent{content, intent.IsCustomPuppet}, ts) if err != nil { portal.log.Errorfln("Failed to handle message %s: %v", info.Id, err) return