mirror of
https://github.com/matrix-org/dendrite
synced 2024-12-14 21:13:52 +01:00
Remove empty fields from /sync
response (#2755)
First attempt at removing empty fields from `/sync` responses. Needs https://github.com/matrix-org/sytest/pull/1298 to keep Sytest happy. Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
This commit is contained in:
parent
c85bc3434f
commit
0f777d421c
7 changed files with 178 additions and 90 deletions
|
@ -170,9 +170,12 @@ func joinResponseWithRooms(syncResponse *types.Response, userID string, roomIDs
|
||||||
Content: []byte(`{"membership":"join"}`),
|
Content: []byte(`{"membership":"join"}`),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
jr, ok := syncResponse.Rooms.Join[roomID]
|
||||||
jr := syncResponse.Rooms.Join[roomID]
|
if !ok {
|
||||||
jr.State.Events = roomEvents
|
jr = types.NewJoinResponse()
|
||||||
|
}
|
||||||
|
jr.Timeline = &types.Timeline{}
|
||||||
|
jr.State = &types.ClientEvents{Events: roomEvents}
|
||||||
syncResponse.Rooms.Join[roomID] = jr
|
syncResponse.Rooms.Join[roomID] = jr
|
||||||
}
|
}
|
||||||
return syncResponse
|
return syncResponse
|
||||||
|
@ -191,8 +194,11 @@ func leaveResponseWithRooms(syncResponse *types.Response, userID string, roomIDs
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
lr := syncResponse.Rooms.Leave[roomID]
|
lr, ok := syncResponse.Rooms.Leave[roomID]
|
||||||
lr.Timeline.Events = roomEvents
|
if !ok {
|
||||||
|
lr = types.NewLeaveResponse()
|
||||||
|
}
|
||||||
|
lr.Timeline = &types.Timeline{Events: roomEvents}
|
||||||
syncResponse.Rooms.Leave[roomID] = lr
|
syncResponse.Rooms.Leave[roomID] = lr
|
||||||
}
|
}
|
||||||
return syncResponse
|
return syncResponse
|
||||||
|
@ -328,9 +334,13 @@ func TestKeyChangeCatchupNoNewJoinsButMessages(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
jr := syncResponse.Rooms.Join[roomID]
|
jr, ok := syncResponse.Rooms.Join[roomID]
|
||||||
jr.State.Events = roomStateEvents
|
if !ok {
|
||||||
jr.Timeline.Events = roomTimelineEvents
|
jr = types.NewJoinResponse()
|
||||||
|
}
|
||||||
|
|
||||||
|
jr.State = &types.ClientEvents{Events: roomStateEvents}
|
||||||
|
jr.Timeline = &types.Timeline{Events: roomTimelineEvents}
|
||||||
syncResponse.Rooms.Join[roomID] = jr
|
syncResponse.Rooms.Join[roomID] = jr
|
||||||
|
|
||||||
rsAPI := &mockRoomserverAPI{
|
rsAPI := &mockRoomserverAPI{
|
||||||
|
@ -442,8 +452,11 @@ func TestKeyChangeCatchupChangeAndLeftSameRoom(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
lr := syncResponse.Rooms.Leave[roomID]
|
lr, ok := syncResponse.Rooms.Leave[roomID]
|
||||||
lr.Timeline.Events = roomEvents
|
if !ok {
|
||||||
|
lr = types.NewLeaveResponse()
|
||||||
|
}
|
||||||
|
lr.Timeline = &types.Timeline{Events: roomEvents}
|
||||||
syncResponse.Rooms.Leave[roomID] = lr
|
syncResponse.Rooms.Leave[roomID] = lr
|
||||||
|
|
||||||
rsAPI := &mockRoomserverAPI{
|
rsAPI := &mockRoomserverAPI{
|
||||||
|
|
|
@ -90,9 +90,9 @@ func (p *AccountDataStreamProvider) IncrementalSync(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if roomData, ok := dataRes.RoomAccountData[roomID][dataType]; ok {
|
if roomData, ok := dataRes.RoomAccountData[roomID][dataType]; ok {
|
||||||
joinData := *types.NewJoinResponse()
|
joinData, ok := req.Response.Rooms.Join[roomID]
|
||||||
if existing, ok := req.Response.Rooms.Join[roomID]; ok {
|
if !ok {
|
||||||
joinData = existing
|
joinData = types.NewJoinResponse()
|
||||||
}
|
}
|
||||||
joinData.AccountData.Events = append(
|
joinData.AccountData.Events = append(
|
||||||
joinData.AccountData.Events,
|
joinData.AccountData.Events,
|
||||||
|
|
|
@ -65,7 +65,7 @@ func (p *InviteStreamProvider) IncrementalSync(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ir := types.NewInviteResponse(inviteEvent)
|
ir := types.NewInviteResponse(inviteEvent)
|
||||||
req.Response.Rooms.Invite[roomID] = *ir
|
req.Response.Rooms.Invite[roomID] = ir
|
||||||
}
|
}
|
||||||
|
|
||||||
// When doing an initial sync, we don't want to add retired invites, as this
|
// When doing an initial sync, we don't want to add retired invites, as this
|
||||||
|
@ -87,7 +87,7 @@ func (p *InviteStreamProvider) IncrementalSync(
|
||||||
Type: "m.room.member",
|
Type: "m.room.member",
|
||||||
Content: gomatrixserverlib.RawJSON(`{"membership":"leave"}`),
|
Content: gomatrixserverlib.RawJSON(`{"membership":"leave"}`),
|
||||||
})
|
})
|
||||||
req.Response.Rooms.Leave[roomID] = *lr
|
req.Response.Rooms.Leave[roomID] = lr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ func (p *PDUStreamProvider) CompleteSync(
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
req.Response.Rooms.Join[roomID] = *jr
|
req.Response.Rooms.Join[roomID] = jr
|
||||||
req.Rooms[roomID] = gomatrixserverlib.Join
|
req.Rooms[roomID] = gomatrixserverlib.Join
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ func (p *PDUStreamProvider) CompleteSync(
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
req.Response.Rooms.Peek[peek.RoomID] = *jr
|
req.Response.Rooms.Peek[peek.RoomID] = jr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
// didn't "remove" events, return that the response is limited.
|
// didn't "remove" events, return that the response is limited.
|
||||||
jr.Timeline.Limited = limited && len(events) == len(recentEvents)
|
jr.Timeline.Limited = limited && len(events) == len(recentEvents)
|
||||||
jr.State.Events = gomatrixserverlib.HeaderedToClientEvents(delta.StateEvents, gomatrixserverlib.FormatSync)
|
jr.State.Events = gomatrixserverlib.HeaderedToClientEvents(delta.StateEvents, gomatrixserverlib.FormatSync)
|
||||||
res.Rooms.Join[delta.RoomID] = *jr
|
res.Rooms.Join[delta.RoomID] = jr
|
||||||
|
|
||||||
case gomatrixserverlib.Peek:
|
case gomatrixserverlib.Peek:
|
||||||
jr := types.NewJoinResponse()
|
jr := types.NewJoinResponse()
|
||||||
|
@ -329,7 +329,7 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
jr.Timeline.Events = gomatrixserverlib.HeaderedToClientEvents(recentEvents, gomatrixserverlib.FormatSync)
|
jr.Timeline.Events = gomatrixserverlib.HeaderedToClientEvents(recentEvents, gomatrixserverlib.FormatSync)
|
||||||
jr.Timeline.Limited = limited
|
jr.Timeline.Limited = limited
|
||||||
jr.State.Events = gomatrixserverlib.HeaderedToClientEvents(delta.StateEvents, gomatrixserverlib.FormatSync)
|
jr.State.Events = gomatrixserverlib.HeaderedToClientEvents(delta.StateEvents, gomatrixserverlib.FormatSync)
|
||||||
res.Rooms.Peek[delta.RoomID] = *jr
|
res.Rooms.Peek[delta.RoomID] = jr
|
||||||
|
|
||||||
case gomatrixserverlib.Leave:
|
case gomatrixserverlib.Leave:
|
||||||
fallthrough // transitions to leave are the same as ban
|
fallthrough // transitions to leave are the same as ban
|
||||||
|
@ -342,7 +342,7 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
// didn't "remove" events, return that the response is limited.
|
// didn't "remove" events, return that the response is limited.
|
||||||
lr.Timeline.Limited = limited && len(events) == len(recentEvents)
|
lr.Timeline.Limited = limited && len(events) == len(recentEvents)
|
||||||
lr.State.Events = gomatrixserverlib.HeaderedToClientEvents(delta.StateEvents, gomatrixserverlib.FormatSync)
|
lr.State.Events = gomatrixserverlib.HeaderedToClientEvents(delta.StateEvents, gomatrixserverlib.FormatSync)
|
||||||
res.Rooms.Leave[delta.RoomID] = *lr
|
res.Rooms.Leave[delta.RoomID] = lr
|
||||||
}
|
}
|
||||||
|
|
||||||
return latestPosition, nil
|
return latestPosition, nil
|
||||||
|
|
|
@ -4,9 +4,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/syncapi/storage"
|
"github.com/matrix-org/dendrite/syncapi/storage"
|
||||||
"github.com/matrix-org/dendrite/syncapi/types"
|
"github.com/matrix-org/dendrite/syncapi/types"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ReceiptStreamProvider struct {
|
type ReceiptStreamProvider struct {
|
||||||
|
@ -76,7 +77,7 @@ func (p *ReceiptStreamProvider) IncrementalSync(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
jr := *types.NewJoinResponse()
|
jr := types.NewJoinResponse()
|
||||||
if existing, ok := req.Response.Rooms.Join[roomID]; ok {
|
if existing, ok := req.Response.Rooms.Join[roomID]; ok {
|
||||||
jr = existing
|
jr = existing
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/caching"
|
"github.com/matrix-org/dendrite/internal/caching"
|
||||||
"github.com/matrix-org/dendrite/syncapi/storage"
|
"github.com/matrix-org/dendrite/syncapi/storage"
|
||||||
"github.com/matrix-org/dendrite/syncapi/types"
|
"github.com/matrix-org/dendrite/syncapi/types"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TypingStreamProvider struct {
|
type TypingStreamProvider struct {
|
||||||
|
@ -35,9 +36,9 @@ func (p *TypingStreamProvider) IncrementalSync(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
jr := *types.NewJoinResponse()
|
jr, ok := req.Response.Rooms.Join[roomID]
|
||||||
if existing, ok := req.Response.Rooms.Join[roomID]; ok {
|
if !ok {
|
||||||
jr = existing
|
jr = types.NewJoinResponse()
|
||||||
}
|
}
|
||||||
|
|
||||||
if users, updated := p.EDUCache.GetTypingUsersIfUpdatedAfter(
|
if users, updated := p.EDUCache.GetTypingUsersIfUpdatedAfter(
|
||||||
|
|
|
@ -327,29 +327,57 @@ type PrevEventRef struct {
|
||||||
PrevSender string `json:"prev_sender"`
|
PrevSender string `json:"prev_sender"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeviceLists struct {
|
||||||
|
Changed []string `json:"changed,omitempty"`
|
||||||
|
Left []string `json:"left,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RoomsResponse struct {
|
||||||
|
Join map[string]*JoinResponse `json:"join,omitempty"`
|
||||||
|
Peek map[string]*JoinResponse `json:"peek,omitempty"`
|
||||||
|
Invite map[string]*InviteResponse `json:"invite,omitempty"`
|
||||||
|
Leave map[string]*LeaveResponse `json:"leave,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToDeviceResponse struct {
|
||||||
|
Events []gomatrixserverlib.SendToDeviceEvent `json:"events,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Response represents a /sync API response. See https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync
|
// Response represents a /sync API response. See https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync
|
||||||
type Response struct {
|
type Response struct {
|
||||||
NextBatch StreamingToken `json:"next_batch"`
|
NextBatch StreamingToken `json:"next_batch"`
|
||||||
AccountData struct {
|
AccountData *ClientEvents `json:"account_data,omitempty"`
|
||||||
Events []gomatrixserverlib.ClientEvent `json:"events,omitempty"`
|
Presence *ClientEvents `json:"presence,omitempty"`
|
||||||
} `json:"account_data,omitempty"`
|
Rooms *RoomsResponse `json:"rooms,omitempty"`
|
||||||
Presence struct {
|
ToDevice *ToDeviceResponse `json:"to_device,omitempty"`
|
||||||
Events []gomatrixserverlib.ClientEvent `json:"events,omitempty"`
|
DeviceLists *DeviceLists `json:"device_lists,omitempty"`
|
||||||
} `json:"presence,omitempty"`
|
DeviceListsOTKCount map[string]int `json:"device_one_time_keys_count,omitempty"`
|
||||||
Rooms struct {
|
}
|
||||||
Join map[string]JoinResponse `json:"join,omitempty"`
|
|
||||||
Peek map[string]JoinResponse `json:"peek,omitempty"`
|
func (r Response) MarshalJSON() ([]byte, error) {
|
||||||
Invite map[string]InviteResponse `json:"invite,omitempty"`
|
type alias Response
|
||||||
Leave map[string]LeaveResponse `json:"leave,omitempty"`
|
a := alias(r)
|
||||||
} `json:"rooms,omitempty"`
|
if r.AccountData != nil && len(r.AccountData.Events) == 0 {
|
||||||
ToDevice struct {
|
a.AccountData = nil
|
||||||
Events []gomatrixserverlib.SendToDeviceEvent `json:"events,omitempty"`
|
}
|
||||||
} `json:"to_device,omitempty"`
|
if r.Presence != nil && len(r.Presence.Events) == 0 {
|
||||||
DeviceLists struct {
|
a.Presence = nil
|
||||||
Changed []string `json:"changed,omitempty"`
|
}
|
||||||
Left []string `json:"left,omitempty"`
|
if r.DeviceLists != nil {
|
||||||
} `json:"device_lists,omitempty"`
|
if len(r.DeviceLists.Left) == 0 && len(r.DeviceLists.Changed) == 0 {
|
||||||
DeviceListsOTKCount map[string]int `json:"device_one_time_keys_count,omitempty"`
|
a.DeviceLists = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.Rooms != nil {
|
||||||
|
if len(r.Rooms.Join) == 0 && len(r.Rooms.Peek) == 0 &&
|
||||||
|
len(r.Rooms.Invite) == 0 && len(r.Rooms.Leave) == 0 {
|
||||||
|
a.Rooms = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.ToDevice != nil && len(r.ToDevice.Events) == 0 {
|
||||||
|
a.ToDevice = nil
|
||||||
|
}
|
||||||
|
return json.Marshal(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Response) HasUpdates() bool {
|
func (r *Response) HasUpdates() bool {
|
||||||
|
@ -370,18 +398,21 @@ func NewResponse() *Response {
|
||||||
res := Response{}
|
res := Response{}
|
||||||
// Pre-initialise the maps. Synapse will return {} even if there are no rooms under a specific section,
|
// Pre-initialise the maps. Synapse will return {} even if there are no rooms under a specific section,
|
||||||
// so let's do the same thing. Bonus: this means we can't get dreaded 'assignment to entry in nil map' errors.
|
// so let's do the same thing. Bonus: this means we can't get dreaded 'assignment to entry in nil map' errors.
|
||||||
res.Rooms.Join = map[string]JoinResponse{}
|
res.Rooms = &RoomsResponse{
|
||||||
res.Rooms.Peek = map[string]JoinResponse{}
|
Join: map[string]*JoinResponse{},
|
||||||
res.Rooms.Invite = map[string]InviteResponse{}
|
Peek: map[string]*JoinResponse{},
|
||||||
res.Rooms.Leave = map[string]LeaveResponse{}
|
Invite: map[string]*InviteResponse{},
|
||||||
|
Leave: map[string]*LeaveResponse{},
|
||||||
|
}
|
||||||
|
|
||||||
// Also pre-intialise empty slices or else we'll insert 'null' instead of '[]' for the value.
|
// Also pre-intialise empty slices or else we'll insert 'null' instead of '[]' for the value.
|
||||||
// TODO: We really shouldn't have to do all this to coerce encoding/json to Do The Right Thing. We should
|
// TODO: We really shouldn't have to do all this to coerce encoding/json to Do The Right Thing. We should
|
||||||
// really be using our own Marshal/Unmarshal implementations otherwise this may prove to be a CPU bottleneck.
|
// really be using our own Marshal/Unmarshal implementations otherwise this may prove to be a CPU bottleneck.
|
||||||
// This also applies to NewJoinResponse, NewInviteResponse and NewLeaveResponse.
|
// This also applies to NewJoinResponse, NewInviteResponse and NewLeaveResponse.
|
||||||
res.AccountData.Events = []gomatrixserverlib.ClientEvent{}
|
res.AccountData = &ClientEvents{}
|
||||||
res.Presence.Events = []gomatrixserverlib.ClientEvent{}
|
res.Presence = &ClientEvents{}
|
||||||
res.ToDevice.Events = []gomatrixserverlib.SendToDeviceEvent{}
|
res.DeviceLists = &DeviceLists{}
|
||||||
|
res.ToDevice = &ToDeviceResponse{}
|
||||||
res.DeviceListsOTKCount = map[string]int{}
|
res.DeviceListsOTKCount = map[string]int{}
|
||||||
|
|
||||||
return &res
|
return &res
|
||||||
|
@ -403,38 +434,73 @@ type UnreadNotifications struct {
|
||||||
NotificationCount int `json:"notification_count"`
|
NotificationCount int `json:"notification_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClientEvents struct {
|
||||||
|
Events []gomatrixserverlib.ClientEvent `json:"events,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Timeline struct {
|
||||||
|
Events []gomatrixserverlib.ClientEvent `json:"events"`
|
||||||
|
Limited bool `json:"limited"`
|
||||||
|
PrevBatch *TopologyToken `json:"prev_batch,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Summary struct {
|
||||||
|
Heroes []string `json:"m.heroes,omitempty"`
|
||||||
|
JoinedMemberCount *int `json:"m.joined_member_count,omitempty"`
|
||||||
|
InvitedMemberCount *int `json:"m.invited_member_count,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// JoinResponse represents a /sync response for a room which is under the 'join' or 'peek' key.
|
// JoinResponse represents a /sync response for a room which is under the 'join' or 'peek' key.
|
||||||
type JoinResponse struct {
|
type JoinResponse struct {
|
||||||
Summary struct {
|
Summary *Summary `json:"summary,omitempty"`
|
||||||
Heroes []string `json:"m.heroes,omitempty"`
|
State *ClientEvents `json:"state,omitempty"`
|
||||||
JoinedMemberCount *int `json:"m.joined_member_count,omitempty"`
|
Timeline *Timeline `json:"timeline,omitempty"`
|
||||||
InvitedMemberCount *int `json:"m.invited_member_count,omitempty"`
|
Ephemeral *ClientEvents `json:"ephemeral,omitempty"`
|
||||||
} `json:"summary"`
|
AccountData *ClientEvents `json:"account_data,omitempty"`
|
||||||
State struct {
|
|
||||||
Events []gomatrixserverlib.ClientEvent `json:"events"`
|
|
||||||
} `json:"state"`
|
|
||||||
Timeline struct {
|
|
||||||
Events []gomatrixserverlib.ClientEvent `json:"events"`
|
|
||||||
Limited bool `json:"limited"`
|
|
||||||
PrevBatch *TopologyToken `json:"prev_batch,omitempty"`
|
|
||||||
} `json:"timeline"`
|
|
||||||
Ephemeral struct {
|
|
||||||
Events []gomatrixserverlib.ClientEvent `json:"events"`
|
|
||||||
} `json:"ephemeral"`
|
|
||||||
AccountData struct {
|
|
||||||
Events []gomatrixserverlib.ClientEvent `json:"events"`
|
|
||||||
} `json:"account_data"`
|
|
||||||
*UnreadNotifications `json:"unread_notifications,omitempty"`
|
*UnreadNotifications `json:"unread_notifications,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (jr JoinResponse) MarshalJSON() ([]byte, error) {
|
||||||
|
type alias JoinResponse
|
||||||
|
a := alias(jr)
|
||||||
|
if jr.State != nil && len(jr.State.Events) == 0 {
|
||||||
|
a.State = nil
|
||||||
|
}
|
||||||
|
if jr.Ephemeral != nil && len(jr.Ephemeral.Events) == 0 {
|
||||||
|
a.Ephemeral = nil
|
||||||
|
}
|
||||||
|
if jr.AccountData != nil && len(jr.AccountData.Events) == 0 {
|
||||||
|
a.AccountData = nil
|
||||||
|
}
|
||||||
|
if jr.Timeline != nil && len(jr.Timeline.Events) == 0 {
|
||||||
|
a.Timeline = nil
|
||||||
|
}
|
||||||
|
if jr.Summary != nil {
|
||||||
|
var nilPtr int
|
||||||
|
joinedEmpty := jr.Summary.JoinedMemberCount == nil || jr.Summary.JoinedMemberCount == &nilPtr
|
||||||
|
invitedEmpty := jr.Summary.InvitedMemberCount == nil || jr.Summary.InvitedMemberCount == &nilPtr
|
||||||
|
if joinedEmpty && invitedEmpty && len(jr.Summary.Heroes) == 0 {
|
||||||
|
a.Summary = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if jr.UnreadNotifications != nil &&
|
||||||
|
jr.UnreadNotifications.NotificationCount == 0 && jr.UnreadNotifications.HighlightCount == 0 {
|
||||||
|
a.UnreadNotifications = nil
|
||||||
|
}
|
||||||
|
return json.Marshal(a)
|
||||||
|
}
|
||||||
|
|
||||||
// NewJoinResponse creates an empty response with initialised arrays.
|
// NewJoinResponse creates an empty response with initialised arrays.
|
||||||
func NewJoinResponse() *JoinResponse {
|
func NewJoinResponse() *JoinResponse {
|
||||||
res := JoinResponse{}
|
return &JoinResponse{
|
||||||
res.State.Events = []gomatrixserverlib.ClientEvent{}
|
Summary: &Summary{},
|
||||||
res.Timeline.Events = []gomatrixserverlib.ClientEvent{}
|
State: &ClientEvents{},
|
||||||
res.Ephemeral.Events = []gomatrixserverlib.ClientEvent{}
|
Timeline: &Timeline{},
|
||||||
res.AccountData.Events = []gomatrixserverlib.ClientEvent{}
|
Ephemeral: &ClientEvents{},
|
||||||
return &res
|
AccountData: &ClientEvents{},
|
||||||
|
UnreadNotifications: &UnreadNotifications{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InviteResponse represents a /sync response for a room which is under the 'invite' key.
|
// InviteResponse represents a /sync response for a room which is under the 'invite' key.
|
||||||
|
@ -469,21 +535,28 @@ func NewInviteResponse(event *gomatrixserverlib.HeaderedEvent) *InviteResponse {
|
||||||
|
|
||||||
// LeaveResponse represents a /sync response for a room which is under the 'leave' key.
|
// LeaveResponse represents a /sync response for a room which is under the 'leave' key.
|
||||||
type LeaveResponse struct {
|
type LeaveResponse struct {
|
||||||
State struct {
|
State *ClientEvents `json:"state,omitempty"`
|
||||||
Events []gomatrixserverlib.ClientEvent `json:"events"`
|
Timeline *Timeline `json:"timeline,omitempty"`
|
||||||
} `json:"state"`
|
}
|
||||||
Timeline struct {
|
|
||||||
Events []gomatrixserverlib.ClientEvent `json:"events"`
|
func (lr LeaveResponse) MarshalJSON() ([]byte, error) {
|
||||||
Limited bool `json:"limited"`
|
type alias LeaveResponse
|
||||||
PrevBatch *TopologyToken `json:"prev_batch,omitempty"`
|
a := alias(lr)
|
||||||
} `json:"timeline"`
|
if lr.State != nil && len(lr.State.Events) == 0 {
|
||||||
|
a.State = nil
|
||||||
|
}
|
||||||
|
if lr.Timeline != nil && len(lr.Timeline.Events) == 0 {
|
||||||
|
a.Timeline = nil
|
||||||
|
}
|
||||||
|
return json.Marshal(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLeaveResponse creates an empty response with initialised arrays.
|
// NewLeaveResponse creates an empty response with initialised arrays.
|
||||||
func NewLeaveResponse() *LeaveResponse {
|
func NewLeaveResponse() *LeaveResponse {
|
||||||
res := LeaveResponse{}
|
res := LeaveResponse{
|
||||||
res.State.Events = []gomatrixserverlib.ClientEvent{}
|
State: &ClientEvents{},
|
||||||
res.Timeline.Events = []gomatrixserverlib.ClientEvent{}
|
Timeline: &Timeline{},
|
||||||
|
}
|
||||||
return &res
|
return &res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue