Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SyncStateHas check function #440

Merged
merged 3 commits into from
Sep 2, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,22 @@ func SyncTimelineHasEventID(roomID string, eventID string) SyncCheckOpt {
})
}

// Check that the state section for `roomID` has an event which passes the check function.
// Note that the state section of a sync response only contains the change in state up to the start
// of the timeline and will not contain the entire state of the room for incremental or
// `lazy_load_members` syncs.
func SyncStateHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be careful here, because this can be misused. The state section of the room contains the state at the start of the timeline, so it's entirely possible that the state to check is in the timeline and not the state. We should be very careful about checking one or the other. What is the use case here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultimately I would like to check that a lazy_load_members /sync response includes the membership of a given sender in the state section. The sender joined the room before the syncing user and their membership is not expected to appear in the timeline. The planned usage looks like this:

syncRes, _ := alice.MustSync(t,
	client.SyncReq{
		Since:  previousSyncToken,
		Filter: buildLazyLoadingSyncFilter(nil),
	},
)

err = client.SyncTimelineHasEventID(serverRoom.RoomID, event.EventID())(alice.UserID, syncRes)
if err != nil {
	t.Errorf("Did not find message in lazy-loading /sync response: %s", err)
}

err := client.SyncStateHasStateKey(serverRoom.RoomID, "m.room.member", event.Sender())(alice.UserID, syncRes)
if err != nil {
	t.Errorf("Did not find %s's m.room.member event in lazy-loading /sync response: %s", event.Sender(), err)
}

I'm avoiding MustSyncUntil because it wouldn't fail immediately if event appears in the timeline without the corresponding sender membership, and the message is expected to already be available via /sync.

return func(clientUserID string, topLevelSyncJSON gjson.Result) error {
err := loopArray(
topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".state.events", check,
)
if err == nil {
return nil
}
return fmt.Errorf("SyncStateHas(%s): %s", roomID, err)
}
}

func SyncEphemeralHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt {
return func(clientUserID string, topLevelSyncJSON gjson.Result) error {
err := loopArray(
Expand Down