瀏覽代碼

Fix bridging receipts with multiple message IDs

Tulir Asokan 3 年之前
父節點
當前提交
6b260dceda
共有 3 個文件被更改,包括 27 次插入53 次删除
  1. 1 1
      go.mod
  2. 2 2
      go.sum
  3. 24 50
      user.go

+ 1 - 1
go.mod

@@ -8,7 +8,7 @@ require (
 	github.com/mattn/go-sqlite3 v1.14.9
 	github.com/prometheus/client_golang v1.11.0
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
-	go.mau.fi/whatsmeow v0.0.0-20211109215855-2e8804d7e690
+	go.mau.fi/whatsmeow v0.0.0-20211110182414-ba28bae40fb5
 	golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
 	google.golang.org/protobuf v1.27.1
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b

+ 2 - 2
go.sum

@@ -139,8 +139,8 @@ github.com/tidwall/sjson v1.2.3 h1:5+deguEhHSEjmuICXZ21uSSsXotWMA0orU783+Z7Cp8=
 github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
 go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910 h1:9FFhG0OmkuMau5UEaTgiUQ+7cSbtbOQ7hiWKdN8OI3I=
 go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910/go.mod h1:AufGrvVh+00Nc07Jm4hTquh7yleZyn20tKJI2wCPAKg=
-go.mau.fi/whatsmeow v0.0.0-20211109215855-2e8804d7e690 h1:Yx5v2ut+kd5YG+bLhCxqPnCEZ+yau2wKsQerk3VYtbY=
-go.mau.fi/whatsmeow v0.0.0-20211109215855-2e8804d7e690/go.mod h1:8jUjOAi3xtGubxcZgG8uSHpAdyQXBRbWAfxkctX/4y4=
+go.mau.fi/whatsmeow v0.0.0-20211110182414-ba28bae40fb5 h1:ERlXDWd0vj62SldgFSqCkjtVpyUgmxRtyKMH20ADW7Q=
+go.mau.fi/whatsmeow v0.0.0-20211110182414-ba28bae40fb5/go.mod h1:8jUjOAi3xtGubxcZgG8uSHpAdyQXBRbWAfxkctX/4y4=
 golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

+ 24 - 50
user.go

@@ -722,58 +722,32 @@ func (user *User) handleReceipt(receipt *events.Receipt) {
 	if portal == nil || len(portal.MXID) == 0 {
 		return
 	}
-	if receipt.IsFromMe {
-		user.markSelfRead(portal, receipt.MessageID)
-	} else {
-		intent := user.bridge.GetPuppetByJID(receipt.Sender).IntentFor(portal)
-		ok := user.markOtherRead(portal, intent, receipt.MessageID)
-		if !ok {
-			// Message not found, try any previous IDs
-			for i := len(receipt.PreviousIDs) - 1; i >= 0; i-- {
-				ok = user.markOtherRead(portal, intent, receipt.PreviousIDs[i])
-				if ok {
-					break
-				}
-			}
+	// 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
+	// know which one is last
+	markAsRead := make([]*database.Message, 0, 1)
+	var bestTimestamp time.Time
+	for _, msgID := range receipt.MessageIDs {
+		msg := user.bridge.DB.Message.GetByJID(portal.Key, msgID)
+		if msg == nil || msg.IsFakeMXID() {
+			continue
 		}
-	}
-}
-
-func (user *User) markOtherRead(portal *Portal, intent *appservice.IntentAPI, messageID types.MessageID) bool {
-	msg := user.bridge.DB.Message.GetByJID(portal.Key, messageID)
-	if msg == nil || msg.IsFakeMXID() {
-		return false
-	}
-
-	err := intent.MarkReadWithContent(portal.MXID, msg.MXID, &CustomReadReceipt{DoublePuppet: intent.IsCustomPuppet})
-	if err != nil {
-		user.log.Warnfln("Failed to mark message %s as read by %s: %v", msg.MXID, intent.UserID, err)
-	}
-	return true
-}
-
-func (user *User) markSelfRead(portal *Portal, messageID types.MessageID) {
-	puppet := user.bridge.GetPuppetByCustomMXID(user.MXID)
-	if puppet == nil || puppet.CustomIntent() == nil {
-		return
-	}
-	var message *database.Message
-	if messageID == "" {
-		message = user.bridge.DB.Message.GetLastInChat(portal.Key)
-		if message == nil {
-			return
+		if msg.Timestamp.After(bestTimestamp) {
+			bestTimestamp = msg.Timestamp
+			markAsRead = append(markAsRead[:0], msg)
+		} else if msg != nil && msg.Timestamp.Equal(bestTimestamp) {
+			markAsRead = append(markAsRead, msg)
 		}
-		user.log.Debugfln("User read chat %s/%s in WhatsApp mobile (last known event: %s/%s)", portal.Key.JID, portal.MXID, message.JID, message.MXID)
-	} else {
-		message = user.bridge.DB.Message.GetByJID(portal.Key, messageID)
-		if message == nil || message.IsFakeMXID() {
-			return
-		}
-		user.log.Debugfln("User read message %s/%s in %s/%s in WhatsApp mobile", message.JID, message.MXID, portal.Key.JID, portal.MXID)
 	}
-	err := puppet.CustomIntent().MarkReadWithContent(portal.MXID, message.MXID, &CustomReadReceipt{DoublePuppet: true})
-	if err != nil {
-		user.log.Warnfln("Failed to bridge own read receipt in %s: %v", portal.Key.JID, err)
+	intent := user.bridge.GetPuppetByJID(receipt.Sender).IntentFor(portal)
+	for _, msg := range markAsRead {
+		err := intent.MarkReadWithContent(portal.MXID, msg.MXID, &CustomReadReceipt{DoublePuppet: intent.IsCustomPuppet})
+		if err != nil {
+			user.log.Warnfln("Failed to mark message %s as read by %s: %v", msg.MXID, intent.UserID, err)
+		} else {
+			user.log.Debugfln("Marked %s as read by %s", msg.MXID, intent.UserID)
+		}
 	}
 }
 
@@ -788,7 +762,7 @@ func (user *User) markSelfReadFull(portal *Portal) {
 	}
 	err := puppet.CustomIntent().MarkReadWithContent(portal.MXID, lastMessage.MXID, &CustomReadReceipt{DoublePuppet: true})
 	if err != nil {
-		user.log.Warnfln("Failed to mark %s in %s as read after backfill: %v", lastMessage.MXID, portal.MXID, err)
+		user.log.Warnfln("Failed to mark %s (last message) in %s as read: %v", lastMessage.MXID, portal.MXID, err)
 	}
 }