Add option to not set room meta in encrypted rooms

This commit is contained in:
Tulir Asokan 2023-04-14 13:40:34 +03:00
parent ac5ca1965b
commit 0fcb64c1aa
6 changed files with 67 additions and 52 deletions

View file

@ -1,5 +1,5 @@
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
// Copyright (C) 2021 Tulir Asokan
// Copyright (C) 2023 Tulir Asokan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
@ -99,7 +99,7 @@ type BridgeConfig struct {
DoublePuppetAllowDiscovery bool `yaml:"double_puppet_allow_discovery"`
LoginSharedSecretMap map[string]string `yaml:"login_shared_secret_map"`
PrivateChatPortalMeta bool `yaml:"private_chat_portal_meta"`
PrivateChatPortalMeta string `yaml:"private_chat_portal_meta"`
ParallelMemberSync bool `yaml:"parallel_member_sync"`
BridgeNotices bool `yaml:"bridge_notices"`
ResendBridgeInfo bool `yaml:"resend_bridge_info"`

View file

@ -77,7 +77,15 @@ func DoUpgrade(helper *up.Helper) {
} else {
helper.Copy(up.Map, "bridge", "login_shared_secret_map")
}
helper.Copy(up.Bool, "bridge", "private_chat_portal_meta")
if legacyPrivateChatPortalMeta, ok := helper.Get(up.Bool, "bridge", "private_chat_portal_meta"); ok {
updatedPrivateChatPortalMeta := "default"
if legacyPrivateChatPortalMeta == "true" {
updatedPrivateChatPortalMeta = "always"
}
helper.Set(up.Str, updatedPrivateChatPortalMeta, "bridge", "private_chat_portal_meta")
} else {
helper.Copy(up.Str, "bridge", "private_chat_portal_meta")
}
helper.Copy(up.Bool, "bridge", "parallel_member_sync")
helper.Copy(up.Bool, "bridge", "bridge_notices")
helper.Copy(up.Bool, "bridge", "resend_bridge_info")

View file

@ -254,9 +254,11 @@ bridge:
# manually.
login_shared_secret_map:
example.com: foobar
# Should the bridge explicitly set the avatar and room name for private chat portal rooms?
# This is implicitly enabled in encrypted rooms.
private_chat_portal_meta: false
# Whether to explicitly set the avatar and room name for private chat portal rooms.
# If set to `default`, this will be enabled in encrypted rooms and disabled in unencrypted rooms.
# If set to `always`, all DM rooms will have explicit names and avatars set.
# If set to `never`, DM rooms will never have names and avatars set.
private_chat_portal_meta: default
# Should group members be synced in parallel? This makes member sync faster
parallel_member_sync: false
# Should Matrix m.notice-type messages be bridged?

View file

@ -67,16 +67,9 @@ func (br *WABridge) createPrivatePortalFromInvite(roomID id.RoomID, inviter *Use
}
portal.MXID = roomID
portal.Topic = PrivateChatTopic
_, _ = portal.MainIntent().SetRoomTopic(portal.MXID, portal.Topic)
if portal.bridge.Config.Bridge.PrivateChatPortalMeta || br.Config.Bridge.Encryption.Default || encryptionEnabled {
portal.Name = puppet.Displayname
portal.AvatarURL = puppet.AvatarURL
portal.Avatar = puppet.Avatar
_, _ = portal.MainIntent().SetRoomName(portal.MXID, portal.Name)
_, _ = portal.MainIntent().SetRoomAvatar(portal.MXID, portal.AvatarURL)
} else {
portal.Name = ""
}
portal.Name = puppet.Displayname
portal.AvatarURL = puppet.AvatarURL
portal.Avatar = puppet.Avatar
portal.log.Infofln("Created private chat portal in %s after invite from %s", roomID, inviter.MXID)
intent := puppet.DefaultIntent()
@ -100,6 +93,13 @@ func (br *WABridge) createPrivatePortalFromInvite(roomID id.RoomID, inviter *Use
br.AS.StateStore.SetMembership(roomID, br.Bot.UserID, event.MembershipJoin)
portal.Encrypted = true
}
_, _ = portal.MainIntent().SetRoomTopic(portal.MXID, portal.Topic)
if portal.shouldSetDMRoomMetadata() {
_, err = portal.MainIntent().SetRoomName(portal.MXID, portal.Name)
portal.NameSet = err == nil
_, err = portal.MainIntent().SetRoomAvatar(portal.MXID, portal.AvatarURL)
portal.AvatarSet = err == nil
}
portal.Update(nil)
portal.UpdateBridgeInfo()
_, _ = intent.SendNotice(roomID, "Private chat portal created")

View file

@ -1156,7 +1156,7 @@ func (portal *Portal) UpdateName(name string, setBy types.JID, updateInfo bool)
if name == "" && portal.IsBroadcastList() {
name = UnnamedBroadcastName
}
if portal.Name != name || (!portal.NameSet && len(portal.MXID) > 0) {
if portal.Name != name || (!portal.NameSet && len(portal.MXID) > 0 && portal.shouldSetDMRoomMetadata()) {
portal.log.Debugfln("Updating name %q -> %q", portal.Name, name)
portal.Name = name
portal.NameSet = false
@ -1164,7 +1164,9 @@ func (portal *Portal) UpdateName(name string, setBy types.JID, updateInfo bool)
defer portal.Update(nil)
}
if len(portal.MXID) > 0 {
if len(portal.MXID) > 0 && !portal.shouldSetDMRoomMetadata() {
portal.UpdateBridgeInfo()
} else if len(portal.MXID) > 0 {
intent := portal.MainIntent()
if !setBy.IsEmpty() {
intent = portal.bridge.GetPuppetByJID(setBy).IntentFor(portal)
@ -1497,6 +1499,12 @@ func (portal *Portal) updateChildRooms() {
}
}
func (portal *Portal) shouldSetDMRoomMetadata() bool {
return !portal.IsPrivateChat() ||
portal.bridge.Config.Bridge.PrivateChatPortalMeta == "always" ||
(portal.IsEncrypted() && portal.bridge.Config.Bridge.PrivateChatPortalMeta != "never")
}
func (portal *Portal) GetEncryptionEventContent() (evt *event.EncryptionEventContent) {
evt = &event.EncryptionEventContent{Algorithm: id.AlgorithmMegolmV1}
if rot := portal.bridge.Config.Bridge.Encryption.Rotation; rot.EnableCustom {
@ -1524,13 +1532,9 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
if portal.IsPrivateChat() {
puppet := portal.bridge.GetPuppetByJID(portal.Key.JID)
puppet.SyncContact(user, true, false, "creating private chat portal")
if portal.bridge.Config.Bridge.PrivateChatPortalMeta || portal.bridge.Config.Bridge.Encryption.Default {
portal.Name = puppet.Displayname
portal.AvatarURL = puppet.AvatarURL
portal.Avatar = puppet.Avatar
} else {
portal.Name = ""
}
portal.Name = puppet.Displayname
portal.AvatarURL = puppet.AvatarURL
portal.Avatar = puppet.Avatar
portal.Topic = PrivateChatTopic
} else if portal.IsStatusBroadcastList() {
if !portal.bridge.Config.Bridge.EnableStatusBroadcast {
@ -1616,18 +1620,7 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
Content: event.Content{Parsed: bridgeInfo},
StateKey: &bridgeInfoStateKey,
}}
if !portal.AvatarURL.IsEmpty() {
initialState = append(initialState, &event.Event{
Type: event.StateRoomAvatar,
Content: event.Content{
Parsed: event.RoomAvatarEventContent{URL: portal.AvatarURL},
},
})
portal.AvatarSet = true
}
var invite []id.UserID
if portal.bridge.Config.Bridge.Encryption.Default {
initialState = append(initialState, &event.Event{
Type: event.StateEncryption,
@ -1640,6 +1633,17 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
invite = append(invite, portal.bridge.Bot.UserID)
}
}
if !portal.AvatarURL.IsEmpty() && portal.shouldSetDMRoomMetadata() {
initialState = append(initialState, &event.Event{
Type: event.StateRoomAvatar,
Content: event.Content{
Parsed: event.RoomAvatarEventContent{URL: portal.AvatarURL},
},
})
portal.AvatarSet = true
} else {
portal.AvatarSet = false
}
creationContent := make(map[string]interface{})
if !portal.bridge.Config.Bridge.FederateRooms {
@ -1674,7 +1678,7 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
invite = append(invite, user.MXID)
}
}
resp, err := intent.CreateRoom(&mautrix.ReqCreateRoom{
req := &mautrix.ReqCreateRoom{
Visibility: "private",
Name: portal.Name,
Topic: portal.Topic,
@ -1685,14 +1689,18 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i
CreationContent: creationContent,
BeeperAutoJoinInvites: autoJoinInvites,
})
}
if !portal.shouldSetDMRoomMetadata() {
req.Name = ""
}
resp, err := intent.CreateRoom(req)
if err != nil {
return err
}
portal.log.Infoln("Matrix room created:", resp.RoomID)
portal.InSpace = false
portal.NameSet = len(portal.Name) > 0
portal.TopicSet = len(portal.Topic) > 0
portal.NameSet = len(req.Name) > 0
portal.TopicSet = len(req.Topic) > 0
portal.MXID = resp.RoomID
portal.bridge.portalsLock.Lock()
portal.bridge.portalsByMXID[portal.MXID] = portal

View file

@ -294,29 +294,26 @@ func (puppet *Puppet) UpdateContactInfo() bool {
}
func (puppet *Puppet) updatePortalMeta(meta func(portal *Portal)) {
if puppet.bridge.Config.Bridge.PrivateChatPortalMeta || puppet.bridge.Config.Bridge.Encryption.Allow {
for _, portal := range puppet.bridge.GetAllPortalsByJID(puppet.JID) {
if !puppet.bridge.Config.Bridge.PrivateChatPortalMeta && !portal.Encrypted {
continue
}
// Get room create lock to prevent races between receiving contact info and room creation.
portal.roomCreateLock.Lock()
meta(portal)
portal.roomCreateLock.Unlock()
}
for _, portal := range puppet.bridge.GetAllPortalsByJID(puppet.JID) {
// Get room create lock to prevent races between receiving contact info and room creation.
portal.roomCreateLock.Lock()
meta(portal)
portal.roomCreateLock.Unlock()
}
}
func (puppet *Puppet) updatePortalAvatar() {
puppet.updatePortalMeta(func(portal *Portal) {
if portal.Avatar == puppet.Avatar && portal.AvatarURL == puppet.AvatarURL && portal.AvatarSet {
if portal.Avatar == puppet.Avatar && portal.AvatarURL == puppet.AvatarURL && (portal.AvatarSet || !portal.shouldSetDMRoomMetadata()) {
return
}
portal.AvatarURL = puppet.AvatarURL
portal.Avatar = puppet.Avatar
portal.AvatarSet = false
defer portal.Update(nil)
if len(portal.MXID) > 0 {
if len(portal.MXID) > 0 && !portal.shouldSetDMRoomMetadata() {
portal.UpdateBridgeInfo()
} else if len(portal.MXID) > 0 {
_, err := portal.MainIntent().SetRoomAvatar(portal.MXID, puppet.AvatarURL)
if err != nil {
portal.log.Warnln("Failed to set avatar:", err)