From a021136576ae74d05d2c467b3c81e51795d15692 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 21 Jul 2021 10:36:01 +0100 Subject: [PATCH 1/8] Refactor room creation to allow initial_state --- clientapi/routing/createroom.go | 186 ++++++++++++++++++++++---------- 1 file changed, 130 insertions(+), 56 deletions(-) diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index 2d8867466c..977f7812de 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -43,7 +43,7 @@ type createRoomRequest struct { Visibility string `json:"visibility"` Topic string `json:"topic"` Preset string `json:"preset"` - CreationContent map[string]interface{} `json:"creation_content"` + CreationContent json.RawMessage `json:"creation_content"` InitialState []fledglingEvent `json:"initial_state"` RoomAliasName string `json:"room_alias_name"` GuestCanJoin bool `json:"guest_can_join"` @@ -177,11 +177,6 @@ func createRoom( // Clobber keys: creator, room_version - if r.CreationContent == nil { - r.CreationContent = make(map[string]interface{}, 2) - } - - r.CreationContent["creator"] = userID roomVersion := roomserverVersion.DefaultRoomVersion() if r.RoomVersion != "" { candidateVersion := gomatrixserverlib.RoomVersion(r.RoomVersion) @@ -194,7 +189,6 @@ func createRoom( } roomVersion = candidateVersion } - r.CreationContent["room_version"] = roomVersion // TODO: visibility/presets/raw initial state // TODO: Create room alias association @@ -203,7 +197,7 @@ func createRoom( logger.WithFields(log.Fields{ "userID": userID, "roomID": roomID, - "roomVersion": r.CreationContent["room_version"], + "roomVersion": roomVersion, }).Info("Creating new room") profile, err := appserviceAPI.RetrieveUserProfile(req.Context(), userID, asAPI, accountDB) @@ -212,6 +206,98 @@ func createRoom( return jsonerror.InternalServerError() } + powerLevelContent := eventutil.InitialPowerLevelsContent(userID) + joinRuleContent := gomatrixserverlib.JoinRuleContent{ + JoinRule: gomatrixserverlib.Invite, + } + historyVisibilityContent := gomatrixserverlib.HistoryVisibilityContent{ + HistoryVisibility: historyVisibilityShared, + } + + if r.PowerLevelContentOverride != nil { + // Merge powerLevelContentOverride fields by unmarshalling it atop the defaults + err = json.Unmarshal(r.PowerLevelContentOverride, &powerLevelContent) + if err != nil { + return util.JSONResponse{ + Code: http.StatusBadRequest, + JSON: jsonerror.BadJSON("malformed power_level_content_override"), + } + } + } + + switch r.Preset { + case presetPrivateChat: + joinRuleContent.JoinRule = gomatrixserverlib.Invite + historyVisibilityContent.HistoryVisibility = historyVisibilityShared + case presetTrustedPrivateChat: + joinRuleContent.JoinRule = gomatrixserverlib.Invite + historyVisibilityContent.HistoryVisibility = historyVisibilityShared + // TODO If trusted_private_chat, all invitees are given the same power level as the room creator. + case presetPublicChat: + joinRuleContent.JoinRule = gomatrixserverlib.Public + historyVisibilityContent.HistoryVisibility = historyVisibilityShared + } + + createEvent := fledglingEvent{ + Type: gomatrixserverlib.MRoomCreate, + Content: gomatrixserverlib.CreateContent{ + Creator: userID, + RoomVersion: &roomVersion, + }, + } + powerLevelEvent := fledglingEvent{ + Type: gomatrixserverlib.MRoomPowerLevels, + Content: powerLevelContent, + } + joinRuleEvent := fledglingEvent{ + Type: gomatrixserverlib.MRoomJoinRules, + Content: joinRuleContent, + } + historyVisibilityEvent := fledglingEvent{ + Type: gomatrixserverlib.MRoomHistoryVisibility, + Content: historyVisibilityContent, + } + membershipEvent := fledglingEvent{ + Type: gomatrixserverlib.MRoomHistoryVisibility, + StateKey: userID, + Content: gomatrixserverlib.MemberContent{ + Membership: gomatrixserverlib.Join, + DisplayName: profile.DisplayName, + AvatarURL: profile.AvatarURL, + }, + } + + var nameEvent *fledglingEvent + var topicEvent *fledglingEvent + var guestAccessEvent *fledglingEvent + + if r.Name != "" { + nameEvent = &fledglingEvent{ + Type: gomatrixserverlib.MRoomName, + Content: eventutil.NameContent{ + Name: r.Name, + }, + } + } + + if r.Topic != "" { + topicEvent = &fledglingEvent{ + Type: "m.room.topic", + Content: eventutil.TopicContent{ + Topic: r.Topic, + }, + } + } + + if r.GuestCanJoin { + guestAccessEvent = &fledglingEvent{ + Type: "m.room.guest_access", + Content: eventutil.GuestAccessContent{ + GuestAccess: "can_join", + }, + } + } + var roomAlias string if r.RoomAliasName != "" { roomAlias = fmt.Sprintf("#%s:%s", r.RoomAliasName, cfg.Matrix.ServerName) @@ -232,42 +318,32 @@ func createRoom( } } - membershipContent := gomatrixserverlib.MemberContent{ - Membership: gomatrixserverlib.Join, - DisplayName: profile.DisplayName, - AvatarURL: profile.AvatarURL, - } + var initialStateEvents []fledglingEvent + for i := range r.InitialState { + switch r.InitialState[i].Type { + case gomatrixserverlib.MRoomCreate: + createEvent = r.InitialState[i] - var joinRules, historyVisibility string - switch r.Preset { - case presetPrivateChat: - joinRules = gomatrixserverlib.Invite - historyVisibility = historyVisibilityShared - case presetTrustedPrivateChat: - joinRules = gomatrixserverlib.Invite - historyVisibility = historyVisibilityShared - // TODO If trusted_private_chat, all invitees are given the same power level as the room creator. - case presetPublicChat: - joinRules = gomatrixserverlib.Public - historyVisibility = historyVisibilityShared - default: - // Default room rules, r.Preset was previously checked for valid values so - // only a request with no preset should end up here. - joinRules = gomatrixserverlib.Invite - historyVisibility = historyVisibilityShared - } + case gomatrixserverlib.MRoomPowerLevels: + powerLevelEvent = r.InitialState[i] - var builtEvents []*gomatrixserverlib.HeaderedEvent + case gomatrixserverlib.MRoomJoinRules: + joinRuleEvent = r.InitialState[i] - powerLevelContent := eventutil.InitialPowerLevelsContent(userID) - if r.PowerLevelContentOverride != nil { - // Merge powerLevelContentOverride fields by unmarshalling it atop the defaults - err = json.Unmarshal(r.PowerLevelContentOverride, &powerLevelContent) - if err != nil { - return util.JSONResponse{ - Code: http.StatusBadRequest, - JSON: jsonerror.BadJSON("malformed power_level_content_override"), - } + case gomatrixserverlib.MRoomHistoryVisibility: + historyVisibilityEvent = r.InitialState[i] + + case "m.room.guest_access": + guestAccessEvent = &r.InitialState[i] + + case gomatrixserverlib.MRoomName: + nameEvent = &r.InitialState[i] + + case "m.room.topic": + topicEvent = &r.InitialState[i] + + default: + initialStateEvents = append(initialStateEvents, r.InitialState[i]) } } @@ -290,11 +366,16 @@ func createRoom( // harder to reason about, hence sticking to a strict static ordering. // TODO: Synapse has txn/token ID on each event. Do we need to do this here? eventsToMake := []fledglingEvent{ - {"m.room.create", "", r.CreationContent}, - {"m.room.member", userID, membershipContent}, - {"m.room.power_levels", "", powerLevelContent}, - {"m.room.join_rules", "", gomatrixserverlib.JoinRuleContent{JoinRule: joinRules}}, - {"m.room.history_visibility", "", eventutil.HistoryVisibilityContent{HistoryVisibility: historyVisibility}}, + createEvent, membershipEvent, powerLevelEvent, joinRuleEvent, historyVisibilityEvent, + } + if guestAccessEvent != nil { + eventsToMake = append(eventsToMake, *guestAccessEvent) + } + if nameEvent != nil { + eventsToMake = append(eventsToMake, *nameEvent) + } + if topicEvent != nil { + eventsToMake = append(eventsToMake, *topicEvent) } if roomAlias != "" { // TODO: bit of a chicken and egg problem here as the alias doesn't exist and cannot until we have made the room. @@ -302,19 +383,12 @@ func createRoom( // m.room.aliases is handled when we call roomserver.SetRoomAlias eventsToMake = append(eventsToMake, fledglingEvent{"m.room.canonical_alias", "", eventutil.CanonicalAlias{Alias: roomAlias}}) } - if r.GuestCanJoin { - eventsToMake = append(eventsToMake, fledglingEvent{"m.room.guest_access", "", eventutil.GuestAccessContent{GuestAccess: "can_join"}}) - } - eventsToMake = append(eventsToMake, r.InitialState...) - if r.Name != "" { - eventsToMake = append(eventsToMake, fledglingEvent{"m.room.name", "", eventutil.NameContent{Name: r.Name}}) - } - if r.Topic != "" { - eventsToMake = append(eventsToMake, fledglingEvent{"m.room.topic", "", eventutil.TopicContent{Topic: r.Topic}}) - } + eventsToMake = append(eventsToMake, initialStateEvents...) + // TODO: invite events // TODO: 3pid invite events + var builtEvents []*gomatrixserverlib.HeaderedEvent authEvents := gomatrixserverlib.NewAuthEvents(nil) for i, e := range eventsToMake { depth := i + 1 // depth starts at 1 From 23e392adc507134e473a7f65bc659971fcd0ca84 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 21 Jul 2021 10:43:11 +0100 Subject: [PATCH 2/8] GMSL types --- clientapi/routing/createroom.go | 12 ++++++------ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index 977f7812de..15bb633e43 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -282,7 +282,7 @@ func createRoom( if r.Topic != "" { topicEvent = &fledglingEvent{ - Type: "m.room.topic", + Type: gomatrixserverlib.MRoomTopic, Content: eventutil.TopicContent{ Topic: r.Topic, }, @@ -291,7 +291,7 @@ func createRoom( if r.GuestCanJoin { guestAccessEvent = &fledglingEvent{ - Type: "m.room.guest_access", + Type: gomatrixserverlib.MRoomGuestAccess, Content: eventutil.GuestAccessContent{ GuestAccess: "can_join", }, @@ -333,13 +333,13 @@ func createRoom( case gomatrixserverlib.MRoomHistoryVisibility: historyVisibilityEvent = r.InitialState[i] - case "m.room.guest_access": + case gomatrixserverlib.MRoomGuestAccess: guestAccessEvent = &r.InitialState[i] case gomatrixserverlib.MRoomName: nameEvent = &r.InitialState[i] - case "m.room.topic": + case gomatrixserverlib.MRoomTopic: topicEvent = &r.InitialState[i] default: @@ -381,7 +381,7 @@ func createRoom( // TODO: bit of a chicken and egg problem here as the alias doesn't exist and cannot until we have made the room. // This means we might fail creating the alias but say the canonical alias is something that doesn't exist. // m.room.aliases is handled when we call roomserver.SetRoomAlias - eventsToMake = append(eventsToMake, fledglingEvent{"m.room.canonical_alias", "", eventutil.CanonicalAlias{Alias: roomAlias}}) + eventsToMake = append(eventsToMake, fledglingEvent{gomatrixserverlib.MRoomCanonicalAlias, "", eventutil.CanonicalAlias{Alias: roomAlias}}) } eventsToMake = append(eventsToMake, initialStateEvents...) @@ -477,7 +477,7 @@ func createRoom( fallthrough case gomatrixserverlib.MRoomCanonicalAlias: fallthrough - case "m.room.encryption": // TODO: move this to gmsl + case gomatrixserverlib.MRoomEncryption: fallthrough case gomatrixserverlib.MRoomMember: fallthrough diff --git a/go.mod b/go.mod index 6799dbf557..ec17e64441 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4 github.com/matrix-org/go-sqlite3-js v0.0.0-20210709140738-b0d1ba599a6d github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 - github.com/matrix-org/gomatrixserverlib v0.0.0-20210720141356-d52ec9c4dd2f + github.com/matrix-org/gomatrixserverlib v0.0.0-20210721094149-75792185bf42 github.com/matrix-org/naffka v0.0.0-20210623111924-14ff508b58e0 github.com/matrix-org/pinecone v0.0.0-20210623102758-74f885644c1b github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 diff --git a/go.sum b/go.sum index c93ce2474f..86149343ac 100644 --- a/go.sum +++ b/go.sum @@ -1027,8 +1027,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20210709140738-b0d1ba599a6d/go.mod h1 github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5dLDCud4r0r55eP4j9FuUNpl60Gmntcop4= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20210720141356-d52ec9c4dd2f h1:FP+tOVTX4mw4GPjHJE28UsPkw59ieISgjDtkCwb1vls= -github.com/matrix-org/gomatrixserverlib v0.0.0-20210720141356-d52ec9c4dd2f/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20210721094149-75792185bf42 h1:UsCdEX9G3svG07bBV8RKAWIyGzCgJpbX4BCP1n4ezH8= +github.com/matrix-org/gomatrixserverlib v0.0.0-20210721094149-75792185bf42/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU= github.com/matrix-org/naffka v0.0.0-20210623111924-14ff508b58e0 h1:HZCzy4oVzz55e+cOMiX/JtSF2UOY1evBl2raaE7ACcU= github.com/matrix-org/naffka v0.0.0-20210623111924-14ff508b58e0/go.mod h1:sjyPyRxKM5uw1nD2cJ6O2OxI6GOqyVBfNXqKjBZTBZE= github.com/matrix-org/pinecone v0.0.0-20210623102758-74f885644c1b h1:5X5vdWQ13xrNkJVqaJHPsrt7rKkMJH5iac0EtfOuxSg= From e0e36287173bb1639f85faffe88bee35e9655165 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 21 Jul 2021 10:45:14 +0100 Subject: [PATCH 3/8] Tweaks to alias --- clientapi/routing/createroom.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index 15bb633e43..e242f61b9f 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -270,6 +270,7 @@ func createRoom( var nameEvent *fledglingEvent var topicEvent *fledglingEvent var guestAccessEvent *fledglingEvent + var aliasEvent *fledglingEvent if r.Name != "" { nameEvent = &fledglingEvent{ @@ -316,6 +317,13 @@ func createRoom( if aliasResp.RoomID != "" { return util.MessageResponse(400, "Alias already exists") } + + aliasEvent = &fledglingEvent{ + Type: gomatrixserverlib.MRoomCanonicalAlias, + Content: eventutil.CanonicalAlias{ + Alias: roomAlias, + }, + } } var initialStateEvents []fledglingEvent @@ -377,11 +385,11 @@ func createRoom( if topicEvent != nil { eventsToMake = append(eventsToMake, *topicEvent) } - if roomAlias != "" { + if aliasEvent != nil { // TODO: bit of a chicken and egg problem here as the alias doesn't exist and cannot until we have made the room. // This means we might fail creating the alias but say the canonical alias is something that doesn't exist. // m.room.aliases is handled when we call roomserver.SetRoomAlias - eventsToMake = append(eventsToMake, fledglingEvent{gomatrixserverlib.MRoomCanonicalAlias, "", eventutil.CanonicalAlias{Alias: roomAlias}}) + eventsToMake = append(eventsToMake, *aliasEvent) } eventsToMake = append(eventsToMake, initialStateEvents...) From b1e8489c55210635d3ee29c1f520f9d20e02cdaa Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 21 Jul 2021 10:46:51 +0100 Subject: [PATCH 4/8] Fix ordering --- clientapi/routing/createroom.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index e242f61b9f..362be10151 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -379,6 +379,7 @@ func createRoom( if guestAccessEvent != nil { eventsToMake = append(eventsToMake, *guestAccessEvent) } + eventsToMake = append(eventsToMake, initialStateEvents...) if nameEvent != nil { eventsToMake = append(eventsToMake, *nameEvent) } @@ -391,7 +392,6 @@ func createRoom( // m.room.aliases is handled when we call roomserver.SetRoomAlias eventsToMake = append(eventsToMake, *aliasEvent) } - eventsToMake = append(eventsToMake, initialStateEvents...) // TODO: invite events // TODO: 3pid invite events From 753230eb123e2415472806039995be20f5db7382 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 21 Jul 2021 10:58:09 +0100 Subject: [PATCH 5/8] Fix bugs --- clientapi/routing/createroom.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index 362be10151..bc6fe92060 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -206,6 +206,10 @@ func createRoom( return jsonerror.InternalServerError() } + createContent := gomatrixserverlib.CreateContent{ + Creator: userID, + RoomVersion: &roomVersion, + } powerLevelContent := eventutil.InitialPowerLevelsContent(userID) joinRuleContent := gomatrixserverlib.JoinRuleContent{ JoinRule: gomatrixserverlib.Invite, @@ -239,11 +243,8 @@ func createRoom( } createEvent := fledglingEvent{ - Type: gomatrixserverlib.MRoomCreate, - Content: gomatrixserverlib.CreateContent{ - Creator: userID, - RoomVersion: &roomVersion, - }, + Type: gomatrixserverlib.MRoomCreate, + Content: createContent, } powerLevelEvent := fledglingEvent{ Type: gomatrixserverlib.MRoomPowerLevels, @@ -258,7 +259,7 @@ func createRoom( Content: historyVisibilityContent, } membershipEvent := fledglingEvent{ - Type: gomatrixserverlib.MRoomHistoryVisibility, + Type: gomatrixserverlib.MRoomMember, StateKey: userID, Content: gomatrixserverlib.MemberContent{ Membership: gomatrixserverlib.Join, From f27bda229801ad9576042f336a4f504e5e5ebaee Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 21 Jul 2021 11:09:32 +0100 Subject: [PATCH 6/8] Fix create content --- clientapi/routing/createroom.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index bc6fe92060..d394511a02 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -206,10 +206,15 @@ func createRoom( return jsonerror.InternalServerError() } - createContent := gomatrixserverlib.CreateContent{ - Creator: userID, - RoomVersion: &roomVersion, + createContent := map[string]interface{}{} + if err = json.Unmarshal(r.CreationContent, &createContent); err != nil { + return util.JSONResponse{ + Code: http.StatusBadRequest, + JSON: jsonerror.BadJSON("invalid create content"), + } } + createContent["creator"] = userID + createContent["room_version"] = roomVersion powerLevelContent := eventutil.InitialPowerLevelsContent(userID) joinRuleContent := gomatrixserverlib.JoinRuleContent{ JoinRule: gomatrixserverlib.Invite, @@ -331,7 +336,7 @@ func createRoom( for i := range r.InitialState { switch r.InitialState[i].Type { case gomatrixserverlib.MRoomCreate: - createEvent = r.InitialState[i] + continue case gomatrixserverlib.MRoomPowerLevels: powerLevelEvent = r.InitialState[i] From 60f43e37c24030df82d2b98dc52e6a6644b7c5e5 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 21 Jul 2021 11:19:53 +0100 Subject: [PATCH 7/8] Only unmarshal create content if specified --- clientapi/routing/createroom.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index d394511a02..156abd5210 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -207,10 +207,12 @@ func createRoom( } createContent := map[string]interface{}{} - if err = json.Unmarshal(r.CreationContent, &createContent); err != nil { - return util.JSONResponse{ - Code: http.StatusBadRequest, - JSON: jsonerror.BadJSON("invalid create content"), + if len(r.CreationContent) > 0 { + if err = json.Unmarshal(r.CreationContent, &createContent); err != nil { + return util.JSONResponse{ + Code: http.StatusBadRequest, + JSON: jsonerror.BadJSON("invalid create content"), + } } } createContent["creator"] = userID From 33b3b07b39bd4597c3f2886d6f36e89c7d331a1f Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 21 Jul 2021 12:13:18 +0100 Subject: [PATCH 8/8] Review comments @Kegsay --- clientapi/routing/createroom.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index 156abd5210..4219bb37c8 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -209,6 +209,7 @@ func createRoom( createContent := map[string]interface{}{} if len(r.CreationContent) > 0 { if err = json.Unmarshal(r.CreationContent, &createContent); err != nil { + util.GetLogger(req.Context()).WithError(err).Error("json.Unmarshal for creation_content failed") return util.JSONResponse{ Code: http.StatusBadRequest, JSON: jsonerror.BadJSON("invalid create content"), @@ -229,6 +230,7 @@ func createRoom( // Merge powerLevelContentOverride fields by unmarshalling it atop the defaults err = json.Unmarshal(r.PowerLevelContentOverride, &powerLevelContent) if err != nil { + util.GetLogger(req.Context()).WithError(err).Error("json.Unmarshal for power_level_content_override failed") return util.JSONResponse{ Code: http.StatusBadRequest, JSON: jsonerror.BadJSON("malformed power_level_content_override"), @@ -336,6 +338,11 @@ func createRoom( var initialStateEvents []fledglingEvent for i := range r.InitialState { + if r.InitialState[i].StateKey != "" { + initialStateEvents = append(initialStateEvents, r.InitialState[i]) + continue + } + switch r.InitialState[i].Type { case gomatrixserverlib.MRoomCreate: continue