diff --git a/bridgev2/matrix/connector.go b/bridgev2/matrix/connector.go index cdfc2568..aed6d3bd 100644 --- a/bridgev2/matrix/connector.go +++ b/bridgev2/matrix/connector.go @@ -81,6 +81,8 @@ type Connector struct { MediaConfig mautrix.RespMediaConfig SpecVersions *mautrix.RespVersions + SpecCaps *mautrix.RespCapabilities + specCapsLock sync.Mutex Capabilities *bridgev2.MatrixCapabilities IgnoreUnsupportedServer bool @@ -409,6 +411,21 @@ func (br *Connector) ensureConnection(ctx context.Context) { br.Bot.EnsureAppserviceConnection(ctx) } +func (br *Connector) fetchCapabilities(ctx context.Context) *mautrix.RespCapabilities { + br.specCapsLock.Lock() + defer br.specCapsLock.Unlock() + if br.SpecCaps != nil { + return br.SpecCaps + } + caps, err := br.Bot.Capabilities(ctx) + if err != nil { + br.Log.Err(err).Msg("Failed to fetch capabilities from homeserver") + return nil + } + br.SpecCaps = caps + return caps +} + func (br *Connector) fetchMediaConfig(ctx context.Context) { cfg, err := br.Bot.GetMediaConfig(ctx) if err != nil { diff --git a/bridgev2/matrix/intent.go b/bridgev2/matrix/intent.go index 1f82f77f..44dcbc5b 100644 --- a/bridgev2/matrix/intent.go +++ b/bridgev2/matrix/intent.go @@ -512,6 +512,39 @@ func (br *Connector) getDefaultEncryptionEvent() *event.EncryptionEventContent { return content } +func (as *ASIntent) filterCreateRequestForV12(ctx context.Context, req *mautrix.ReqCreateRoom) { + if as.Connector.Config.Homeserver.Software == bridgeconfig.SoftwareHungry { + // Hungryserv doesn't override the capabilities endpoint nor do room versions + return + } + caps := as.Connector.fetchCapabilities(ctx) + roomVer := req.RoomVersion + if roomVer == "" && caps != nil && caps.RoomVersions != nil { + roomVer = id.RoomVersion(caps.RoomVersions.Default) + } + if roomVer != "" && !roomVer.PrivilegedRoomCreators() { + return + } + creators, _ := req.CreationContent["additional_creators"].([]id.UserID) + creators = append(slices.Clone(creators), as.GetMXID()) + if req.PowerLevelOverride != nil { + for _, creator := range creators { + delete(req.PowerLevelOverride.Users, creator) + } + } + for _, evt := range req.InitialState { + if evt.Type != event.StatePowerLevels { + continue + } + content, ok := evt.Content.Parsed.(*event.PowerLevelsEventContent) + if ok { + for _, creator := range creators { + delete(content.Users, creator) + } + } + } +} + func (as *ASIntent) CreateRoom(ctx context.Context, req *mautrix.ReqCreateRoom) (id.RoomID, error) { if as.Connector.Config.Encryption.Default { req.InitialState = append(req.InitialState, &event.Event{ @@ -527,6 +560,7 @@ func (as *ASIntent) CreateRoom(ctx context.Context, req *mautrix.ReqCreateRoom) } req.CreationContent["m.federate"] = false } + as.filterCreateRequestForV12(ctx, req) resp, err := as.Matrix.CreateRoom(ctx, req) if err != nil { return "", err diff --git a/bridgev2/portal.go b/bridgev2/portal.go index 7d479be2..8bd66b6a 100644 --- a/bridgev2/portal.go +++ b/bridgev2/portal.go @@ -4999,7 +4999,6 @@ func (portal *Portal) createMatrixRoomInLoop(ctx context.Context, source *UserLo IsDirect: portal.RoomType == database.RoomTypeDM, PowerLevelOverride: powerLevels, BeeperLocalRoomID: portal.Bridge.Matrix.GenerateDeterministicRoomID(portal.PortalKey), - RoomVersion: id.RoomV11, } autoJoinInvites := portal.Bridge.Matrix.GetCapabilities().AutoJoinInvites if autoJoinInvites { diff --git a/bridgev2/space.go b/bridgev2/space.go index f6d07922..2ca2bce3 100644 --- a/bridgev2/space.go +++ b/bridgev2/space.go @@ -164,8 +164,7 @@ func (ul *UserLogin) GetSpaceRoom(ctx context.Context) (id.RoomID, error) { ul.UserMXID: 50, }, }, - RoomVersion: id.RoomV11, - Invite: []id.UserID{ul.UserMXID}, + Invite: []id.UserID{ul.UserMXID}, } if autoJoin { req.BeeperInitialMembers = []id.UserID{ul.UserMXID} diff --git a/bridgev2/user.go b/bridgev2/user.go index af9e9694..9a7896d6 100644 --- a/bridgev2/user.go +++ b/bridgev2/user.go @@ -229,9 +229,8 @@ func (user *User) GetManagementRoom(ctx context.Context) (id.RoomID, error) { user.MXID: 50, }, }, - RoomVersion: id.RoomV11, - Invite: []id.UserID{user.MXID}, - IsDirect: true, + Invite: []id.UserID{user.MXID}, + IsDirect: true, } if autoJoin { req.BeeperInitialMembers = []id.UserID{user.MXID}