Skip to content

Commit

Permalink
Add method to get full room state
Browse files Browse the repository at this point in the history
  • Loading branch information
tulir committed Sep 30, 2021
1 parent b5e587d commit b8efcf9
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
9 changes: 8 additions & 1 deletion appservice/intent.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,20 @@ func (intent *IntentAPI) SendMassagedStateEvent(roomID id.RoomID, eventType even
return intent.Client.SendMassagedStateEvent(roomID, eventType, stateKey, contentJSON, ts)
}

func (intent *IntentAPI) StateEvent(roomID id.RoomID, eventType event.Type, stateKey string, outContent interface{}) (err error) {
func (intent *IntentAPI) StateEvent(roomID id.RoomID, eventType event.Type, stateKey string, outContent interface{}) error {
if err := intent.EnsureJoined(roomID); err != nil {
return err
}
return intent.Client.StateEvent(roomID, eventType, stateKey, outContent)
}

func (intent *IntentAPI) State(roomID id.RoomID) (mautrix.RoomStateMap, error) {
if err := intent.EnsureJoined(roomID); err != nil {
return nil, err
}
return intent.Client.State(roomID)
}

func (intent *IntentAPI) Member(roomID id.RoomID, userID id.UserID) *event.MemberEventContent {
member, ok := intent.as.StateStore.TryGetMember(roomID, userID)
if !ok {
Expand Down
49 changes: 49 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,55 @@ func (cli *Client) StateEvent(roomID id.RoomID, eventType event.Type, stateKey s
return
}

// parseRoomStateArray parses a JSON array as a stream and stores the events inside it in a room state map.
func parseRoomStateArray(_ *http.Request, res *http.Response, responseJSON interface{}) ([]byte, error) {
response := make(RoomStateMap)
responsePtr := responseJSON.(*interface{})
*responsePtr = response
dec := json.NewDecoder(res.Body)

arrayStart, err := dec.Token()
if err != nil {
return nil, err
} else if arrayStart != json.Delim('[') {
return nil, fmt.Errorf("expected array start, got %+v", arrayStart)
}

for i := 1; dec.More(); i++ {
var evt *event.Event
err = dec.Decode(&evt)
if err != nil {
return nil, fmt.Errorf("failed to parse state array item #%d: %v", i, err)
}
subMap, ok := response[evt.Type]
if !ok {
subMap = make(map[string]*event.Event)
response[evt.Type] = subMap
}
subMap[*evt.StateKey] = evt
}

arrayEnd, err := dec.Token()
if err != nil {
return nil, err
} else if arrayEnd != json.Delim(']') {
return nil, fmt.Errorf("expected array end, got %+v", arrayStart)
}
return nil, nil
}

// State gets all state in a room.
// See https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-state
func (cli *Client) State(roomID id.RoomID) (stateMap RoomStateMap, err error) {
_, err = cli.MakeFullRequest(FullRequest{
Method: http.MethodGet,
URL: cli.BuildURL("rooms", roomID, "state"),
ResponseJSON: &stateMap,
Handler: parseRoomStateArray,
})
return
}

// UploadLink uploads an HTTP URL and then returns an MXC URI.
func (cli *Client) UploadLink(link string) (*RespMediaUpload, error) {
res, err := cli.Client.Get(link)
Expand Down
6 changes: 4 additions & 2 deletions room.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"maunium.net/go/mautrix/id"
)

type RoomStateMap = map[event.Type]map[string]*event.Event

// Room represents a single Matrix room.
type Room struct {
ID id.RoomID
State map[event.Type]map[string]*event.Event
State RoomStateMap
}

// UpdateState updates the room's current state with the given Event. This will clobber events based
Expand Down Expand Up @@ -47,6 +49,6 @@ func NewRoom(roomID id.RoomID) *Room {
// Init the State map and return a pointer to the Room
return &Room{
ID: roomID,
State: make(map[event.Type]map[string]*event.Event),
State: make(RoomStateMap),
}
}

0 comments on commit b8efcf9

Please sign in to comment.