Browse Source

Add delivery status to MSS events

Tulir Asokan 1 year ago
parent
commit
015cc1f19f
3 changed files with 39 additions and 5 deletions
  1. 9 4
      messagetracking.go
  2. 29 0
      portal.go
  3. 1 1
      user.go

+ 9 - 4
messagetracking.go

@@ -147,7 +147,7 @@ func (portal *Portal) sendErrorMessage(evt *event.Event, err error, msgType stri
 	return resp.EventID
 }
 
-func (portal *Portal) sendStatusEvent(evtID, lastRetry id.EventID, err error) {
+func (portal *Portal) sendStatusEvent(evtID, lastRetry id.EventID, err error, deliveredTo *[]id.UserID) {
 	if !portal.bridge.Config.Bridge.MessageStatusEvents {
 		return
 	}
@@ -165,7 +165,8 @@ func (portal *Portal) sendStatusEvent(evtID, lastRetry id.EventID, err error) {
 			Type:    event.RelReference,
 			EventID: evtID,
 		},
-		LastRetry: lastRetry,
+		DeliveredToUsers: deliveredTo,
+		LastRetry:        lastRetry,
 	}
 	if err == nil {
 		content.Status = event.MessageStatusSuccess
@@ -224,12 +225,16 @@ func (portal *Portal) sendMessageMetrics(evt *event.Event, err error, part strin
 		if sendNotice {
 			ms.setNoticeID(portal.sendErrorMessage(evt, err, msgType, isCertain, ms.getNoticeID()))
 		}
-		portal.sendStatusEvent(origEvtID, evt.ID, err)
+		portal.sendStatusEvent(origEvtID, evt.ID, err, nil)
 	} else {
 		portal.log.Debugfln("Handled Matrix %s %s", msgType, evtDescription)
 		portal.sendDeliveryReceipt(evt.ID)
 		portal.bridge.SendMessageSuccessCheckpoint(evt, status.MsgStepRemote, ms.getRetryNum())
-		portal.sendStatusEvent(origEvtID, evt.ID, nil)
+		var deliveredTo *[]id.UserID
+		if portal.IsPrivateChat() {
+			deliveredTo = &[]id.UserID{}
+		}
+		portal.sendStatusEvent(origEvtID, evt.ID, nil, deliveredTo)
 		if prevNotice := ms.popNoticeID(); prevNotice != "" {
 			_, _ = portal.MainIntent().RedactEvent(portal.MXID, prevNotice, mautrix.ReqRedact{
 				Reason: "error resolved",

+ 29 - 0
portal.go

@@ -48,6 +48,7 @@ import (
 	"go.mau.fi/util/exerrors"
 	"go.mau.fi/util/exmime"
 	"go.mau.fi/util/ffmpeg"
+	"go.mau.fi/util/jsontime"
 	"go.mau.fi/util/random"
 	"go.mau.fi/util/variationselector"
 	"go.mau.fi/whatsmeow"
@@ -62,6 +63,7 @@ import (
 	"maunium.net/go/mautrix/appservice"
 	"maunium.net/go/mautrix/bridge"
 	"maunium.net/go/mautrix/bridge/bridgeconfig"
+	"maunium.net/go/mautrix/bridge/status"
 	"maunium.net/go/mautrix/crypto/attachment"
 	"maunium.net/go/mautrix/event"
 	"maunium.net/go/mautrix/format"
@@ -351,11 +353,38 @@ func (portal *Portal) handleMatrixMessageLoopItem(msg PortalMatrixMessage) {
 	}
 }
 
+func (portal *Portal) handleDeliveryReceipt(receipt *events.Receipt, source *User) {
+	if !portal.IsPrivateChat() {
+		return
+	}
+	for _, msgID := range receipt.MessageIDs {
+		msg := portal.bridge.DB.Message.GetByJID(portal.Key, msgID)
+		if msg == nil || msg.IsFakeMXID() {
+			continue
+		}
+		if msg.Sender == source.JID {
+			portal.bridge.SendRawMessageCheckpoint(&status.MessageCheckpoint{
+				EventID:    msg.MXID,
+				RoomID:     portal.MXID,
+				Step:       status.MsgStepRemote,
+				Timestamp:  jsontime.UM(receipt.Timestamp),
+				Status:     status.MsgStatusDelivered,
+				ReportedBy: status.MsgReportedByBridge,
+			})
+			portal.sendStatusEvent(msg.MXID, "", nil, &[]id.UserID{portal.MainIntent().UserID})
+		}
+	}
+}
+
 func (portal *Portal) handleReceipt(receipt *events.Receipt, source *User) {
 	if receipt.Sender.Server != types.DefaultUserServer {
 		// TODO handle lids
 		return
 	}
+	if receipt.Type == events.ReceiptTypeDelivered {
+		portal.handleDeliveryReceipt(receipt, source)
+		return
+	}
 	// The order of the message ID array depends on the sender's platform, so we just have to find
 	// the last message based on timestamp. Also, timestamps only have second precision, so if
 	// there are many messages at the same second just mark them all as read, because we don't

+ 1 - 1
user.go

@@ -1224,7 +1224,7 @@ func (user *User) handleChatPresence(presence *events.ChatPresence) {
 }
 
 func (user *User) handleReceipt(receipt *events.Receipt) {
-	if receipt.Type != events.ReceiptTypeRead && receipt.Type != events.ReceiptTypeReadSelf {
+	if receipt.Type != events.ReceiptTypeRead && receipt.Type != events.ReceiptTypeReadSelf && receipt.Type != events.ReceiptTypeDelivered {
 		return
 	}
 	portal := user.GetPortalByMessageSource(receipt.MessageSource)