Ver código fonte

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.
Nicolas Werner 5 anos atrás
pai
commit
fc4098d3e4
3 arquivos alterados com 42 adições e 8 exclusões
  1. 2 1
      go.mod
  2. 4 0
      go.sum
  3. 36 7
      portal.go

+ 2 - 1
go.mod

@@ -4,6 +4,7 @@ go 1.11
 
 
 require (
 require (
 	github.com/Rhymen/go-whatsapp v0.0.2-0.20190524185555-8d76e32a6d8e
 	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/lib/pq v1.1.1
 	github.com/mattn/go-sqlite3 v1.10.0
 	github.com/mattn/go-sqlite3 v1.10.0
 	github.com/pkg/errors v0.8.1
 	github.com/pkg/errors v0.8.1
@@ -16,6 +17,6 @@ require (
 )
 )
 
 
 replace (
 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
 	gopkg.in/russross/blackfriday.v2 => github.com/russross/blackfriday/v2 v2.0.1
 )
 )

+ 4 - 0
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/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.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/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 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 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.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 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.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-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 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

+ 36 - 7
portal.go

@@ -33,6 +33,8 @@ import (
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"github.com/chai2010/webp"
+
 	"github.com/Rhymen/go-whatsapp"
 	"github.com/Rhymen/go-whatsapp"
 	waProto "github.com/Rhymen/go-whatsapp/binary/proto"
 	waProto "github.com/Rhymen/go-whatsapp/binary/proto"
 	"maunium.net/go/mautrix/format"
 	"maunium.net/go/mautrix/format"
@@ -189,13 +191,15 @@ func (portal *Portal) handleMessage(msg PortalMessage) {
 	case whatsapp.TextMessage:
 	case whatsapp.TextMessage:
 		portal.HandleTextMessage(msg.source, data)
 		portal.HandleTextMessage(msg.source, data)
 	case whatsapp.ImageMessage:
 	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:
 	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:
 	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:
 	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:
 	case whatsappExt.MessageRevocation:
 		portal.HandleMessageRevoke(msg.source, data)
 		portal.HandleMessageRevoke(msg.source, data)
 	case FakeMessage:
 	case FakeMessage:
@@ -898,7 +902,7 @@ func (portal *Portal) HandleTextMessage(source *User, message whatsapp.TextMessa
 	portal.finishHandling(source, message.Info.Source, resp.EventID)
 	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) {
 	if !portal.startHandling(info) {
 		return
 		return
 	}
 	}
@@ -924,6 +928,25 @@ func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte,
 	if detected := http.DetectContentType(data); detected != "application/octet-stream" {
 	if detected := http.DetectContentType(data); detected != "application/octet-stream" {
 		mimeType = detected
 		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)
 	uploaded, err := intent.UploadBytes(data, mimeType)
 	if err != nil {
 	if err != nil {
 		portal.log.Errorfln("Failed to upload media for %s: %v", err)
 		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]) {
 	switch strings.ToLower(strings.Split(mimeType, "/")[0]) {
 	case "image":
 	case "image":
-		content.MsgType = mautrix.MsgImage
+		if (!sendAsSticker) {
+			content.MsgType = mautrix.MsgImage
+		}
 		cfg, _, _ := image.DecodeConfig(bytes.NewReader(data))
 		cfg, _, _ := image.DecodeConfig(bytes.NewReader(data))
 		content.Info.Width = cfg.Width
 		content.Info.Width = cfg.Width
 		content.Info.Height = cfg.Height
 		content.Info.Height = cfg.Height
@@ -977,7 +1002,11 @@ func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte,
 
 
 	_, _ = intent.UserTyping(portal.MXID, false, 0)
 	_, _ = intent.UserTyping(portal.MXID, false, 0)
 	ts := int64(info.Timestamp * 1000)
 	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 {
 	if err != nil {
 		portal.log.Errorfln("Failed to handle message %s: %v", info.Id, err)
 		portal.log.Errorfln("Failed to handle message %s: %v", info.Id, err)
 		return
 		return