Add config option to bridge cross-room replies

This commit is contained in:
Tulir Asokan 2023-03-08 17:14:31 +02:00
parent 6bea8539ab
commit 6df2ff7259
6 changed files with 47 additions and 9 deletions

View File

@ -118,6 +118,7 @@ type BridgeConfig struct {
CaptionInMessage bool `yaml:"caption_in_message"`
ExtEvPolls bool `yaml:"extev_polls"`
SendWhatsAppEdits bool `yaml:"send_whatsapp_edits"`
CrossRoomReplies bool `yaml:"cross_room_replies"`
MessageHandlingTimeout struct {
ErrorAfterStr string `yaml:"error_after"`

View File

@ -107,6 +107,7 @@ func DoUpgrade(helper *up.Helper) {
helper.Copy(up.Bool, "bridge", "extev_polls")
}
helper.Copy(up.Bool, "bridge", "send_whatsapp_edits")
helper.Copy(up.Bool, "bridge", "cross_room_replies")
helper.Copy(up.Str|up.Null, "bridge", "message_handling_timeout", "error_after")
helper.Copy(up.Str|up.Null, "bridge", "message_handling_timeout", "deadline")

View File

@ -312,6 +312,8 @@ bridge:
# Should Matrix edits be bridged to WhatsApp edits?
# Official WhatsApp clients don't render edits yet, but once they do, the bridge should work with them right away.
send_whatsapp_edits: false
# Should cross-chat replies from WhatsApp be bridged? Most servers and clients don't support this.
cross_room_replies: false
# Maximum time for handling Matrix events. Duration strings formatted for https://pkg.go.dev/time#ParseDuration
# Null means there's no enforced timeout.
message_handling_timeout:

4
go.mod
View File

@ -16,7 +16,7 @@ require (
golang.org/x/net v0.6.0
google.golang.org/protobuf v1.28.1
maunium.net/go/maulogger/v2 v2.4.1
maunium.net/go/mautrix v0.15.0-beta.2
maunium.net/go/mautrix v0.15.0-beta.2.0.20230308151314-83fcdcf30f00
)
require (
@ -37,7 +37,7 @@ require (
github.com/tidwall/sjson v1.2.5 // indirect
github.com/yuin/goldmark v1.5.4 // indirect
go.mau.fi/libsignal v0.1.0 // indirect
go.mau.fi/zeroconfig v0.1.0 // indirect
go.mau.fi/zeroconfig v0.1.1 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect

8
go.sum
View File

@ -69,8 +69,8 @@ go.mau.fi/libsignal v0.1.0 h1:vAKI/nJ5tMhdzke4cTK1fb0idJzz1JuEIpmjprueC+c=
go.mau.fi/libsignal v0.1.0/go.mod h1:R8ovrTezxtUNzCQE5PH30StOQWWeBskBsWE55vMfY9I=
go.mau.fi/whatsmeow v0.0.0-20230306190159-5caded34a872 h1:jrIWy0l9kTxl7bdp3muFofZcyLyI1xxE7BXWeldVKr0=
go.mau.fi/whatsmeow v0.0.0-20230306190159-5caded34a872/go.mod h1:zoTtv1CupGEyTew7TOwnBmTbHB4pVad2OzjTf5CVwa0=
go.mau.fi/zeroconfig v0.1.0 h1:SDGgreQevNJHb+QqGAs2Ff+OPXcGdO8rZencqP4BJi4=
go.mau.fi/zeroconfig v0.1.0/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
go.mau.fi/zeroconfig v0.1.1 h1:igLhBbCkaO8yxtxCfzy28k3yitzXU43LcOwpWmpBjz4=
go.mau.fi/zeroconfig v0.1.1/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
@ -127,5 +127,5 @@ maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
maunium.net/go/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8=
maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho=
maunium.net/go/mautrix v0.15.0-beta.2 h1:J7sEehF7taahVtoCsM6E41VauaBNQMPCCcxYCe/0Zbk=
maunium.net/go/mautrix v0.15.0-beta.2/go.mod h1:AE3TCX9q4W7fYfrL/1RsuOell9rTUBO27XUULuwArH4=
maunium.net/go/mautrix v0.15.0-beta.2.0.20230308151314-83fcdcf30f00 h1:tlEAjIGSnxZd2MDvgAIw946KoxqWQq/SJDEchoCJM0M=
maunium.net/go/mautrix v0.15.0-beta.2.0.20230308151314-83fcdcf30f00/go.mod h1:Ay2u2JljEKX2rEfA2Ss8Wxkj1tkAhUClpA+exZc7imk=

View File

@ -120,6 +120,16 @@ func (br *WABridge) GetPortalByJID(key database.PortalKey) *Portal {
return portal
}
func (br *WABridge) GetExistingPortalByJID(key database.PortalKey) *Portal {
br.portalsLock.Lock()
defer br.portalsLock.Unlock()
portal, ok := br.portalsByJID[key]
if !ok {
return br.loadDBPortal(br.DB.Portal.GetByJID(key), nil)
}
return portal
}
func (br *WABridge) GetAllPortals() []*Portal {
return br.dbPortalsToPortals(br.DB.Portal.GetAll())
}
@ -1866,15 +1876,35 @@ func (portal *Portal) SetReply(content *event.MessageEventContent, replyTo *Repl
if replyTo == nil {
return false
}
message := portal.bridge.DB.Message.GetByJID(portal.Key, replyTo.MessageID)
key := portal.Key
targetPortal := portal
defer func() {
if content.RelatesTo != nil && content.RelatesTo.InReplyTo != nil && targetPortal != portal {
content.RelatesTo.InReplyTo.UnstableRoomID = targetPortal.MXID
}
}()
if portal.bridge.Config.Bridge.CrossRoomReplies && !replyTo.Chat.IsEmpty() && replyTo.Chat != key.JID {
if replyTo.Chat.Server == types.GroupServer {
key = database.NewPortalKey(replyTo.Chat, types.EmptyJID)
} else if replyTo.Chat == types.BroadcastServerJID {
key = database.NewPortalKey(replyTo.Chat, key.Receiver)
}
if key != portal.Key {
targetPortal = portal.bridge.GetExistingPortalByJID(key)
if targetPortal == nil {
return false
}
}
}
message := portal.bridge.DB.Message.GetByJID(key, replyTo.MessageID)
if message == nil || message.IsFakeMXID() {
if isBackfill && portal.bridge.Config.Homeserver.Software == bridgeconfig.SoftwareHungry {
content.RelatesTo = (&event.RelatesTo{}).SetReplyTo(portal.deterministicEventID(replyTo.Sender, replyTo.MessageID, ""))
content.RelatesTo = (&event.RelatesTo{}).SetReplyTo(targetPortal.deterministicEventID(replyTo.Sender, replyTo.MessageID, ""))
return true
}
return false
}
evt, err := portal.MainIntent().GetEvent(portal.MXID, message.MXID)
evt, err := targetPortal.MainIntent().GetEvent(targetPortal.MXID, message.MXID)
if err != nil {
portal.log.Warnln("Failed to get reply target:", err)
content.RelatesTo = (&event.RelatesTo{}).SetReplyTo(message.MXID)
@ -2017,12 +2047,14 @@ func (portal *Portal) sendMessage(intent *appservice.IntentAPI, eventType event.
type ReplyInfo struct {
MessageID types.MessageID
Chat types.JID
Sender types.JID
}
type Replyable interface {
GetStanzaId() string
GetParticipant() string
GetRemoteJid() string
}
func GetReply(replyable Replyable) *ReplyInfo {
@ -2033,8 +2065,10 @@ func GetReply(replyable Replyable) *ReplyInfo {
if err != nil {
return nil
}
chat, _ := types.ParseJID(replyable.GetRemoteJid())
return &ReplyInfo{
MessageID: types.MessageID(replyable.GetStanzaId()),
Chat: chat,
Sender: sender,
}
}