Compare commits

...

10 commits

7 changed files with 65 additions and 48 deletions

View file

@ -95,27 +95,28 @@ type BridgeConfig struct {
DoublePuppetConfig bridgeconfig.DoublePuppetConfig `yaml:",inline"` DoublePuppetConfig bridgeconfig.DoublePuppetConfig `yaml:",inline"`
PrivateChatPortalMeta string `yaml:"private_chat_portal_meta"` PrivateChatPortalMeta string `yaml:"private_chat_portal_meta"`
ParallelMemberSync bool `yaml:"parallel_member_sync"` ParallelMemberSync bool `yaml:"parallel_member_sync"`
BridgeNotices bool `yaml:"bridge_notices"` BridgeNotices bool `yaml:"bridge_notices"`
ResendBridgeInfo bool `yaml:"resend_bridge_info"` ResendBridgeInfo bool `yaml:"resend_bridge_info"`
MuteBridging bool `yaml:"mute_bridging"` MuteBridging bool `yaml:"mute_bridging"`
ArchiveTag string `yaml:"archive_tag"` ArchiveTag string `yaml:"archive_tag"`
PinnedTag string `yaml:"pinned_tag"` PinnedTag string `yaml:"pinned_tag"`
TagOnlyOnCreate bool `yaml:"tag_only_on_create"` TagOnlyOnCreate bool `yaml:"tag_only_on_create"`
MarkReadOnlyOnCreate bool `yaml:"mark_read_only_on_create"` MarkReadOnlyOnCreate bool `yaml:"mark_read_only_on_create"`
EnableStatusBroadcast bool `yaml:"enable_status_broadcast"` EnableStatusBroadcast bool `yaml:"enable_status_broadcast"`
MuteStatusBroadcast bool `yaml:"mute_status_broadcast"` MuteStatusBroadcast bool `yaml:"mute_status_broadcast"`
StatusBroadcastTag string `yaml:"status_broadcast_tag"` StatusBroadcastTag string `yaml:"status_broadcast_tag"`
WhatsappThumbnail bool `yaml:"whatsapp_thumbnail"` WhatsappThumbnail bool `yaml:"whatsapp_thumbnail"`
AllowUserInvite bool `yaml:"allow_user_invite"` AllowUserInvite bool `yaml:"allow_user_invite"`
FederateRooms bool `yaml:"federate_rooms"` FederateRooms bool `yaml:"federate_rooms"`
URLPreviews bool `yaml:"url_previews"` URLPreviews bool `yaml:"url_previews"`
CaptionInMessage bool `yaml:"caption_in_message"` CaptionInMessage bool `yaml:"caption_in_message"`
BeeperGalleries bool `yaml:"beeper_galleries"` BeeperGalleries bool `yaml:"beeper_galleries"`
ExtEvPolls bool `yaml:"extev_polls"` ExtEvPolls bool `yaml:"extev_polls"`
CrossRoomReplies bool `yaml:"cross_room_replies"` CrossRoomReplies bool `yaml:"cross_room_replies"`
DisableReplyFallbacks bool `yaml:"disable_reply_fallbacks"` DisableReplyFallbacks bool `yaml:"disable_reply_fallbacks"`
PrivateChatSelfPuppets bool `yaml:"private_chat_self_puppets"`
MessageHandlingTimeout struct { MessageHandlingTimeout struct {
ErrorAfterStr string `yaml:"error_after"` ErrorAfterStr string `yaml:"error_after"`

View file

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

View file

@ -315,6 +315,10 @@ bridge:
# Disable generating reply fallbacks? Some extremely bad clients still rely on them, # Disable generating reply fallbacks? Some extremely bad clients still rely on them,
# but they're being phased out and will be completely removed in the future. # but they're being phased out and will be completely removed in the future.
disable_reply_fallbacks: false disable_reply_fallbacks: false
# Invite the puppet which represents the bridge user into private chats?
# This allows proper backfilling in private chats without double puppeting enabled,
# but adds an additional puppet user to each private chat.
private_chat_self_puppets: false
# Maximum time for handling Matrix events. Duration strings formatted for https://pkg.go.dev/time#ParseDuration # Maximum time for handling Matrix events. Duration strings formatted for https://pkg.go.dev/time#ParseDuration
# Null means there's no enforced timeout. # Null means there's no enforced timeout.
message_handling_timeout: message_handling_timeout:

View file

@ -172,7 +172,7 @@ func (formatter *Formatter) ParseWhatsApp(ctx context.Context, roomID id.RoomID,
} }
func (formatter *Formatter) ParseMatrix(html string, mentions *event.Mentions) (string, []string) { func (formatter *Formatter) ParseMatrix(html string, mentions *event.Mentions) (string, []string) {
ctx := format.NewContext() ctx := format.NewContext(context.TODO())
var mentionedJIDs []string var mentionedJIDs []string
if mentions != nil { if mentions != nil {
var allowedMentions = make(map[types.JID]bool) var allowedMentions = make(map[types.JID]bool)
@ -202,7 +202,7 @@ func (formatter *Formatter) ParseMatrix(html string, mentions *event.Mentions) (
} }
func (formatter *Formatter) ParseMatrixWithoutMentions(html string) string { func (formatter *Formatter) ParseMatrixWithoutMentions(html string) string {
ctx := format.NewContext() ctx := format.NewContext(context.TODO())
ctx.ReturnData[allowedMentionsContextKey] = map[types.JID]struct{}{} ctx.ReturnData[allowedMentionsContextKey] = map[types.JID]struct{}{}
return formatter.matrixHTMLParser.Parse(html, ctx) return formatter.matrixHTMLParser.Parse(html, ctx)
} }

16
go.mod
View file

@ -12,15 +12,15 @@ require (
github.com/rs/zerolog v1.32.0 github.com/rs/zerolog v1.32.0
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/tidwall/gjson v1.17.1 github.com/tidwall/gjson v1.17.1
go.mau.fi/util v0.4.1 go.mau.fi/util v0.4.2-0.20240318211948-d27d5a4cda9e
go.mau.fi/webp v0.1.0 go.mau.fi/webp v0.1.0
go.mau.fi/whatsmeow v0.0.0-20240326141755-051606b388f6 go.mau.fi/whatsmeow v0.0.0-20240327124018-350073db195c
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8
golang.org/x/image v0.15.0 golang.org/x/image v0.15.0
golang.org/x/net v0.22.0 golang.org/x/net v0.24.0
golang.org/x/sync v0.3.0 golang.org/x/sync v0.7.0
google.golang.org/protobuf v1.33.0 google.golang.org/protobuf v1.33.0
maunium.net/go/mautrix v0.18.0 maunium.net/go/mautrix v0.18.1-0.20240413105730-423d32ddf6d6
) )
require ( require (
@ -42,8 +42,8 @@ require (
github.com/yuin/goldmark v1.7.0 // indirect github.com/yuin/goldmark v1.7.0 // indirect
go.mau.fi/libsignal v0.1.0 // indirect go.mau.fi/libsignal v0.1.0 // indirect
go.mau.fi/zeroconfig v0.1.2 // indirect go.mau.fi/zeroconfig v0.1.2 // indirect
golang.org/x/crypto v0.21.0 // indirect golang.org/x/crypto v0.22.0 // indirect
golang.org/x/sys v0.18.0 // indirect golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

32
go.sum
View file

@ -69,29 +69,29 @@ github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA=
github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
go.mau.fi/libsignal v0.1.0 h1:vAKI/nJ5tMhdzke4cTK1fb0idJzz1JuEIpmjprueC+c= 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/libsignal v0.1.0/go.mod h1:R8ovrTezxtUNzCQE5PH30StOQWWeBskBsWE55vMfY9I=
go.mau.fi/util v0.4.1 h1:3EC9KxIXo5+h869zDGf5OOZklRd/FjeVnimTwtm3owg= go.mau.fi/util v0.4.2-0.20240318211948-d27d5a4cda9e h1:2jdYsZTTIwSo4TGmVrqLgeCqaxexJ9nY2Tuj1MzDIwc=
go.mau.fi/util v0.4.1/go.mod h1:GjkTEBsehYZbSh2LlE6cWEn+6ZIZTGrTMM/5DMNlmFY= go.mau.fi/util v0.4.2-0.20240318211948-d27d5a4cda9e/go.mod h1:GjkTEBsehYZbSh2LlE6cWEn+6ZIZTGrTMM/5DMNlmFY=
go.mau.fi/webp v0.1.0 h1:BHObH/DcFntT9KYun5pDr0Ot4eUZO8k2C7eP7vF4ueA= go.mau.fi/webp v0.1.0 h1:BHObH/DcFntT9KYun5pDr0Ot4eUZO8k2C7eP7vF4ueA=
go.mau.fi/webp v0.1.0/go.mod h1:e42Z+VMFrUMS9cpEwGRIor+lQWO8oUAyPyMtcL+NMt8= go.mau.fi/webp v0.1.0/go.mod h1:e42Z+VMFrUMS9cpEwGRIor+lQWO8oUAyPyMtcL+NMt8=
go.mau.fi/whatsmeow v0.0.0-20240326141755-051606b388f6 h1:CbU9Vq9Bvh03sk+xZO4FOaMTasuPiJbwyqWZsBa+gko= go.mau.fi/whatsmeow v0.0.0-20240327124018-350073db195c h1:a5O4nqmwUWvmC+27RUdefkuy5XzMOEUqR9ji+/BcHZA=
go.mau.fi/whatsmeow v0.0.0-20240326141755-051606b388f6/go.mod h1:kNI5foyzqd77d5HaWc1Jico6/rxtZ/UE8nr80hIsbIk= go.mau.fi/whatsmeow v0.0.0-20240327124018-350073db195c/go.mod h1:kNI5foyzqd77d5HaWc1Jico6/rxtZ/UE8nr80hIsbIk=
go.mau.fi/zeroconfig v0.1.2 h1:DKOydWnhPMn65GbXZOafgkPm11BvFashZWLct0dGFto= go.mau.fi/zeroconfig v0.1.2 h1:DKOydWnhPMn65GbXZOafgkPm11BvFashZWLct0dGFto=
go.mau.fi/zeroconfig v0.1.2/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70= go.mau.fi/zeroconfig v0.1.2/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f h1:3CW0unweImhOzd5FmYuRsD4Y4oQFKZIjAnKbjV4WIrw= golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc=
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
@ -105,5 +105,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= 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/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
maunium.net/go/mautrix v0.18.0 h1:sNsApeSWB8x0hLjGcdmi5JqO6Tvp2PVkiSStz+Yas6k= maunium.net/go/mautrix v0.18.1-0.20240413105730-423d32ddf6d6 h1:zSGNGm31EzKYDmKJG2VS5wYqYDAT5pJhFfGauR6r4yU=
maunium.net/go/mautrix v0.18.0/go.mod h1:STwJZ+6CAeiEQs7fYCkd5aC12XR5DXANE6Swy/PBKGo= maunium.net/go/mautrix v0.18.1-0.20240413105730-423d32ddf6d6/go.mod h1:STwJZ+6CAeiEQs7fYCkd5aC12XR5DXANE6Swy/PBKGo=

View file

@ -1216,7 +1216,7 @@ func (portal *Portal) getMessageIntent(ctx context.Context, user *User, info *ty
return nil return nil
} }
intent := puppet.IntentFor(portal) intent := puppet.IntentFor(portal)
if !intent.IsCustomPuppet && portal.IsPrivateChat() && info.Sender.User == portal.Key.Receiver.User && portal.Key.Receiver != portal.Key.JID { if !portal.bridge.Config.Bridge.PrivateChatSelfPuppets && !intent.IsCustomPuppet && portal.IsPrivateChat() && info.Sender.User == portal.Key.Receiver.User && portal.Key.Receiver != portal.Key.JID {
zerolog.Ctx(ctx).Debug().Msg("Not handling message: user doesn't have double puppeting enabled") zerolog.Ctx(ctx).Debug().Msg("Not handling message: user doesn't have double puppeting enabled")
return nil return nil
} }
@ -2180,6 +2180,10 @@ func (portal *Portal) CreateMatrixRoom(ctx context.Context, user *User, groupInf
invite = append(invite, portal.bridge.Bot.UserID) invite = append(invite, portal.bridge.Bot.UserID)
} }
} }
if portal.IsPrivateChat() && portal.bridge.Config.Bridge.PrivateChatSelfPuppets {
rec := portal.bridge.GetPuppetByJID(portal.Key.Receiver)
invite = append(invite, rec.MXID)
}
if !portal.AvatarURL.IsEmpty() && portal.shouldSetDMRoomMetadata() { if !portal.AvatarURL.IsEmpty() && portal.shouldSetDMRoomMetadata() {
initialState = append(initialState, &event.Event{ initialState = append(initialState, &event.Event{
Type: event.StateRoomAvatar, Type: event.StateRoomAvatar,
@ -2303,6 +2307,13 @@ func (portal *Portal) CreateMatrixRoom(ctx context.Context, user *User, groupInf
log.Err(err).Msg("Failed to ensure bridge bot is joined to created portal") log.Err(err).Msg("Failed to ensure bridge bot is joined to created portal")
} }
} }
if portal.bridge.Config.Bridge.PrivateChatSelfPuppets {
rec := portal.bridge.GetPuppetByJID(portal.Key.Receiver)
err = rec.DefaultIntent().EnsureJoined(ctx, portal.MXID)
if err != nil {
log.Err(err).Msg("Failed to join created portal with puppet")
}
}
user.UpdateDirectChats(ctx, map[id.UserID][]id.RoomID{puppet.MXID: {portal.MXID}}) user.UpdateDirectChats(ctx, map[id.UserID][]id.RoomID{puppet.MXID: {portal.MXID}})
} else if portal.IsParent { } else if portal.IsParent {