dendrite/zion/store.go
2022-11-01 23:17:48 -07:00

173 lines
4.2 KiB
Go

/*
Convenient function for space info mapping between Matrix room and Space contract
*/
package zion
import (
"context"
"encoding/json"
"strings"
roomserver "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib"
)
type ClientRoomserverStore struct {
rsAPI roomserver.ClientRoomserverAPI
}
type SyncRoomserverStore struct {
rsAPI roomserver.SyncRoomserverAPI
}
type StoreAPI interface {
GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo
}
func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo {
result := RoomInfo{
QueryUserId: userId.MatrixUserId,
SpaceNetworkId: "",
ChannelNetworkId: "",
RoomType: Unknown,
IsOwner: false,
}
createTuple := gomatrixserverlib.StateKeyTuple{
EventType: gomatrixserverlib.MRoomCreate,
StateKey: "",
}
spaceChildTuple := gomatrixserverlib.StateKeyTuple{
EventType: ConstSpaceChildEventType,
StateKey: "*",
}
spaceParentTuple := gomatrixserverlib.StateKeyTuple{
EventType: ConstSpaceParentEventType,
StateKey: "*",
}
var roomEvents roomserver.QueryCurrentStateResponse
err := s.rsAPI.QueryCurrentState(context.Background(), &roomserver.QueryCurrentStateRequest{
RoomID: roomId,
AllowWildcards: true,
StateTuples: []gomatrixserverlib.StateKeyTuple{
createTuple,
spaceParentTuple,
spaceChildTuple,
},
}, &roomEvents)
if err != nil {
return result
}
//TODO: replace with HydrateRoomInfoWithStateEvents when you have a practical way to flatten roomEvents map
for _, state := range roomEvents.StateEvents {
switch state.Type() {
case gomatrixserverlib.MRoomCreate:
var creatorEvent CreatorEvent
err := json.Unmarshal(roomEvents.StateEvents[createTuple].Content(), &creatorEvent)
result.IsOwner = strings.HasPrefix(
creatorEvent.Creator,
userId.LocalPart,
)
if err == nil {
result.RoomType = Space
result.SpaceNetworkId = roomId
}
case ConstSpaceChildEventType:
result.RoomType = Space
result.SpaceNetworkId = roomId
case ConstSpaceParentEventType:
result.RoomType = Channel
result.SpaceNetworkId = *state.StateKey()
result.ChannelNetworkId = roomId
}
}
return result
}
func (s *SyncRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo {
result := RoomInfo{
QueryUserId: userId.MatrixUserId,
SpaceNetworkId: "",
ChannelNetworkId: "",
RoomType: Unknown,
IsOwner: false,
}
createTuple := gomatrixserverlib.StateKeyTuple{
EventType: gomatrixserverlib.MRoomCreate,
StateKey: "",
}
spaceChildTuple := gomatrixserverlib.StateKeyTuple{
EventType: ConstSpaceChildEventType,
StateKey: "*",
}
spaceParentTuple := gomatrixserverlib.StateKeyTuple{
EventType: ConstSpaceParentEventType,
StateKey: "*",
}
var roomEvents roomserver.QueryLatestEventsAndStateResponse
err := s.rsAPI.QueryLatestEventsAndState(context.Background(),
&roomserver.QueryLatestEventsAndStateRequest{
RoomID: roomId,
StateToFetch: []gomatrixserverlib.StateKeyTuple{
createTuple,
spaceParentTuple,
spaceChildTuple,
},
}, &roomEvents)
if err != nil {
return result
}
HydrateRoomInfoWithStateEvents(roomId, userId, &result, roomEvents.StateEvents)
return result
}
func HydrateRoomInfoWithStateEvents(roomId string, userId UserIdentifier, r *RoomInfo, stateEvents []*gomatrixserverlib.HeaderedEvent) {
for _, state := range stateEvents {
switch state.Type() {
case gomatrixserverlib.MRoomCreate:
var creatorEvent CreatorEvent
err := json.Unmarshal(state.Content(), &creatorEvent)
r.IsOwner = strings.HasPrefix(
creatorEvent.Creator,
userId.LocalPart,
)
if err == nil {
r.RoomType = Space
r.SpaceNetworkId = roomId
}
case ConstSpaceChildEventType:
r.RoomType = Space
r.SpaceNetworkId = roomId
case ConstSpaceParentEventType:
r.RoomType = Channel
r.SpaceNetworkId = *state.StateKey()
r.ChannelNetworkId = roomId
}
}
}
func NewClientRoomserverStore(rsAPI roomserver.ClientRoomserverAPI) StoreAPI {
return &ClientRoomserverStore{
rsAPI: rsAPI,
}
}
func NewSyncRoomserverStore(rsAPI roomserver.SyncRoomserverAPI) StoreAPI {
return &SyncRoomserverStore{
rsAPI: rsAPI,
}
}