Browse Source

Add support for multi-contact messages

Tulir Asokan 3 years ago
parent
commit
e2b0879f16
3 changed files with 52 additions and 2 deletions
  1. 1 0
      CHANGELOG.md
  2. 11 0
      historysync.go
  3. 40 2
      portal.go

+ 1 - 0
CHANGELOG.md

@@ -4,6 +4,7 @@
 * Added overrides for mime type -> file extension mapping as some OSes have
   very obscure extensions in their mime type database.
 * Added support for personal filtering spaces (started by [@HelderFSFerreira] and [@clmnin] in [#413]).
+* Added support for multi-contact messages.
 * Fixed avatar remove events from WhatsApp being ignored.
 * Fixed the bridge using the wrong Olm session if a client established a new
   one due to corruption.

+ 11 - 0
historysync.go

@@ -23,6 +23,7 @@ import (
 
 	waProto "go.mau.fi/whatsmeow/binary/proto"
 	"go.mau.fi/whatsmeow/types"
+
 	"maunium.net/go/mautrix"
 	"maunium.net/go/mautrix/appservice"
 	"maunium.net/go/mautrix/event"
@@ -509,6 +510,16 @@ func (portal *Portal) appendBatchEvents(converted *ConvertedMessage, info *types
 		*eventsArray = append(*eventsArray, mainEvt)
 		*infoArray = append(*infoArray, info)
 	}
+	if converted.MultiEvent != nil {
+		for _, subEvtContent := range converted.MultiEvent {
+			subEvt, err := portal.wrapBatchEvent(info, converted.Intent, converted.Type, subEvtContent, nil)
+			if err != nil {
+				return err
+			}
+			*eventsArray = append(*eventsArray, subEvt)
+			*infoArray = append(*infoArray, nil)
+		}
+	}
 	return nil
 }
 

+ 40 - 2
portal.go

@@ -267,7 +267,7 @@ func containsSupportedMessage(waMsg *waProto.Message) bool {
 	return waMsg.Conversation != nil || waMsg.ExtendedTextMessage != nil || waMsg.ImageMessage != nil ||
 		waMsg.StickerMessage != nil || waMsg.AudioMessage != nil || waMsg.VideoMessage != nil ||
 		waMsg.DocumentMessage != nil || waMsg.ContactMessage != nil || waMsg.LocationMessage != nil ||
-		waMsg.LiveLocationMessage != nil || waMsg.GroupInviteMessage != nil
+		waMsg.LiveLocationMessage != nil || waMsg.GroupInviteMessage != nil || waMsg.ContactsArrayMessage != nil
 }
 
 func isPotentiallyInteresting(waMsg *waProto.Message) bool {
@@ -276,7 +276,7 @@ func isPotentiallyInteresting(waMsg *waProto.Message) bool {
 	}
 	// List of message types that aren't supported, but might potentially be interesting
 	// (so a warning should be logged if they are encountered).
-	return waMsg.Call != nil || waMsg.Chat != nil || waMsg.ContactsArrayMessage != nil ||
+	return waMsg.Call != nil || waMsg.Chat != nil ||
 		waMsg.HighlyStructuredMessage != nil || waMsg.SendPaymentMessage != nil || waMsg.LiveLocationMessage != nil ||
 		waMsg.RequestPaymentMessage != nil || waMsg.DeclinePaymentRequestMessage != nil ||
 		waMsg.CancelPaymentRequestMessage != nil || waMsg.TemplateMessage != nil ||
@@ -304,6 +304,8 @@ func getMessageType(waMsg *waProto.Message) string {
 		return fmt.Sprintf("document %s", waMsg.GetDocumentMessage().GetMimetype())
 	case waMsg.ContactMessage != nil:
 		return "contact"
+	case waMsg.ContactsArrayMessage != nil:
+		return "contact array"
 	case waMsg.LocationMessage != nil:
 		return "location"
 	case waMsg.LiveLocationMessage != nil:
@@ -342,6 +344,8 @@ func (portal *Portal) convertMessage(intent *appservice.IntentAPI, source *User,
 		return portal.convertMediaMessage(intent, source, info, waMsg.GetDocumentMessage())
 	case waMsg.ContactMessage != nil:
 		return portal.convertContactMessage(intent, waMsg.GetContactMessage())
+	case waMsg.ContactsArrayMessage != nil:
+		return portal.convertContactsArrayMessage(intent, waMsg.GetContactsArrayMessage())
 	case waMsg.LocationMessage != nil:
 		return portal.convertLocationMessage(intent, waMsg.GetLocationMessage())
 	case waMsg.LiveLocationMessage != nil:
@@ -478,6 +482,14 @@ func (portal *Portal) handleMessage(source *User, evt *events.Message) {
 				eventID = resp.EventID
 			}
 		}
+		if converted.MultiEvent != nil && existingMsg == nil {
+			for index, subEvt := range converted.MultiEvent {
+				resp, err = portal.sendMessage(converted.Intent, converted.Type, subEvt, nil, evt.Info.Timestamp.UnixMilli())
+				if err != nil {
+					portal.log.Errorfln("Failed to send sub-event %d of %s to Matrix: %v", index+1, msgID, err)
+				}
+			}
+		}
 		if len(eventID) != 0 {
 			portal.finishHandling(existingMsg, &evt.Info, resp.EventID, false)
 		}
@@ -1302,6 +1314,8 @@ type ConvertedMessage struct {
 	Extra   map[string]interface{}
 	Caption *event.MessageEventContent
 
+	MultiEvent []*event.MessageEventContent
+
 	ReplyTo types.MessageID
 }
 
@@ -1455,6 +1469,30 @@ func (portal *Portal) convertContactMessage(intent *appservice.IntentAPI, msg *w
 	}
 }
 
+func (portal *Portal) convertContactsArrayMessage(intent *appservice.IntentAPI, msg *waProto.ContactsArrayMessage) *ConvertedMessage {
+	name := msg.GetDisplayName()
+	if len(name) == 0 {
+		name = fmt.Sprintf("%d contacts", len(msg.GetContacts()))
+	}
+	contacts := make([]*event.MessageEventContent, 0, len(msg.GetContacts()))
+	for _, contact := range msg.GetContacts() {
+		converted := portal.convertContactMessage(intent, contact)
+		if converted != nil {
+			contacts = append(contacts, converted.Content)
+		}
+	}
+	return &ConvertedMessage{
+		Intent: intent,
+		Type:   event.EventMessage,
+		Content: &event.MessageEventContent{
+			MsgType: event.MsgNotice,
+			Body:    fmt.Sprintf("Sent %s", name),
+		},
+		ReplyTo:    msg.GetContextInfo().GetStanzaId(),
+		MultiEvent: contacts,
+	}
+}
+
 func (portal *Portal) tryKickUser(userID id.UserID, intent *appservice.IntentAPI) error {
 	_, err := intent.KickUser(portal.MXID, &mautrix.ReqKickUser{UserID: userID})
 	if err != nil {