diff --git a/go.mod b/go.mod index 5ae69c5..cba4e91 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( golang.org/x/net v0.0.0-20220812174116-3211cb980234 google.golang.org/protobuf v1.28.1 maunium.net/go/maulogger/v2 v2.3.2 - maunium.net/go/mautrix v0.12.2-0.20221008135414-78f80c20b158 + maunium.net/go/mautrix v0.12.2-0.20221010132912-8a069bfe741f ) require ( diff --git a/go.sum b/go.sum index 68115b3..3138c49 100644 --- a/go.sum +++ b/go.sum @@ -100,5 +100,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.3.2 h1:1XmIYmMd3PoQfp9J+PaHhpt80zpfmMqaShzUTC7FwY0= maunium.net/go/maulogger/v2 v2.3.2/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A= -maunium.net/go/mautrix v0.12.2-0.20221008135414-78f80c20b158 h1:Q56l5MDNzcmL5E0+wsGRKyjFlgSTQ73JeTYQ2LdZ8FY= -maunium.net/go/mautrix v0.12.2-0.20221008135414-78f80c20b158/go.mod h1:/jxQFIipObSsjZPH6o3xyUi8uoULz3Hfr/8p9loqpYE= +maunium.net/go/mautrix v0.12.2-0.20221010132912-8a069bfe741f h1:oXcakqZ7dIAKNVXUrKjDJO6Yl4Gk1RbXJFBrDZJvaI8= +maunium.net/go/mautrix v0.12.2-0.20221010132912-8a069bfe741f/go.mod h1:/jxQFIipObSsjZPH6o3xyUi8uoULz3Hfr/8p9loqpYE= diff --git a/portal.go b/portal.go index 6241f3d..30bc961 100644 --- a/portal.go +++ b/portal.go @@ -942,21 +942,27 @@ func (portal *Portal) syncParticipant(source *User, participant types.GroupParti } }() puppet.SyncContact(source, true, false, "group participant") - if user != nil && user != source { - portal.ensureUserInvited(user) - } - if user == nil || !puppet.IntentFor(portal).IsCustomPuppet { - err := puppet.IntentFor(portal).EnsureJoined(portal.MXID) - if err != nil { - portal.log.Warnfln("Failed to make puppet of %s join %s: %v", participant.JID, portal.MXID, err) + if portal.MXID != "" { + if user != nil && user != source { + portal.ensureUserInvited(user) + } + if user == nil || !puppet.IntentFor(portal).IsCustomPuppet { + err := puppet.IntentFor(portal).EnsureJoined(portal.MXID) + if err != nil { + portal.log.Warnfln("Failed to make puppet of %s join %s: %v", participant.JID, portal.MXID, err) + } } } } -func (portal *Portal) SyncParticipants(source *User, metadata *types.GroupInfo) { +func (portal *Portal) SyncParticipants(source *User, metadata *types.GroupInfo) ([]id.UserID, *event.PowerLevelsEventContent) { changed := false - levels, err := portal.MainIntent().PowerLevels(portal.MXID) - if err != nil { + var levels *event.PowerLevelsEventContent + var err error + if portal.MXID != "" { + levels, err = portal.MainIntent().PowerLevels(portal.MXID) + } + if levels == nil || err != nil { levels = portal.GetBasePowerLevels() changed = true } @@ -964,6 +970,7 @@ func (portal *Portal) SyncParticipants(source *User, metadata *types.GroupInfo) var wg sync.WaitGroup wg.Add(len(metadata.Participants)) participantMap := make(map[types.JID]bool) + userIDs := make([]id.UserID, 0, len(metadata.Participants)) for _, participant := range metadata.Participants { portal.log.Debugfln("Syncing participant %s (admin: %t)", participant.JID, participant.IsAdmin) participantMap[participant.JID] = true @@ -983,18 +990,25 @@ func (portal *Portal) SyncParticipants(source *User, metadata *types.GroupInfo) } changed = levels.EnsureUserLevel(puppet.MXID, expectedLevel) || changed if user != nil { + userIDs = append(userIDs, user.MXID) changed = levels.EnsureUserLevel(user.MXID, expectedLevel) || changed } - } - if changed { - _, err = portal.MainIntent().SetPowerLevels(portal.MXID, levels) - if err != nil { - portal.log.Errorln("Failed to change power levels:", err) + if user == nil || puppet.CustomMXID != user.MXID { + userIDs = append(userIDs, puppet.MXID) } } - portal.kickExtraUsers(participantMap) + if portal.MXID != "" { + if changed { + _, err = portal.MainIntent().SetPowerLevels(portal.MXID, levels) + if err != nil { + portal.log.Errorln("Failed to change power levels:", err) + } + } + portal.kickExtraUsers(participantMap) + } wg.Wait() portal.log.Debugln("Participant sync completed") + return userIDs, levels } func reuploadAvatar(intent *appservice.IntentAPI, url string) (id.ContentURI, error) { @@ -1517,6 +1531,21 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i if !portal.bridge.Config.Bridge.FederateRooms { creationContent["m.federate"] = false } + autoJoinInvites := portal.bridge.Config.Homeserver.Software == bridgeconfig.SoftwareHungry + if autoJoinInvites { + portal.log.Debugfln("Hungryserv mode: adding all group members in create request") + if groupInfo != nil { + // TODO non-hungryserv could also include all members in invites, and then send joins manually? + participants, powerLevels := portal.SyncParticipants(user, groupInfo) + invite = append(invite, participants...) + if initialState[0].Type != event.StatePowerLevels { + panic(fmt.Errorf("unexpected type %s in first initial state event", initialState[0].Type.Type)) + } + initialState[0].Content.Parsed = powerLevels + } else { + invite = append(invite, user.MXID) + } + } resp, err := intent.CreateRoom(&mautrix.ReqCreateRoom{ Visibility: "private", Name: portal.Name, @@ -1526,6 +1555,8 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i IsDirect: portal.IsPrivateChat(), InitialState: initialState, CreationContent: creationContent, + + BeeperAutoJoinInvites: autoJoinInvites, }) if err != nil { return err @@ -1540,11 +1571,17 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i portal.log.Infoln("Matrix room created:", portal.MXID) // We set the memberships beforehand to make sure the encryption key exchange in initial backfill knows the users are here. + inviteMembership := event.MembershipInvite + if autoJoinInvites { + inviteMembership = event.MembershipJoin + } for _, userID := range invite { - portal.bridge.StateStore.SetMembership(portal.MXID, userID, event.MembershipInvite) + portal.bridge.StateStore.SetMembership(portal.MXID, userID, inviteMembership) } - portal.ensureUserInvited(user) + if !autoJoinInvites { + portal.ensureUserInvited(user) + } user.syncChatDoublePuppetDetails(portal, true) go portal.addToSpace(user) @@ -1554,7 +1591,9 @@ func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo, i portal.ExpirationTime = groupInfo.DisappearingTimer portal.Update(nil) } - portal.SyncParticipants(user, groupInfo) + if !autoJoinInvites { + portal.SyncParticipants(user, groupInfo) + } if groupInfo.IsAnnounce { portal.RestrictMessageSending(groupInfo.IsAnnounce) }