@@ -2,6 +2,7 @@ package matrix
22
33import (
44 "context"
5+ "encoding/json"
56 "errors"
67 "fmt"
78 "net/http"
@@ -94,21 +95,66 @@ func (mc *MatrixClient) SendMessage(ctx context.Context, userID id.UserID, roomI
9495}
9596
9697// Sync performs a sync for the specified user to fetch messages.
97- func (mc * MatrixClient ) Sync (ctx context.Context , userID id.UserID , since string ) (* mautrix.RespSync , error ) {
98+ // If filterAfterEventID is provided (non-empty), uses post-processing to filter events.
99+ func (mc * MatrixClient ) Sync (ctx context.Context , userID id.UserID , since , filterAfterEventID string ) (* mautrix.RespSync , error ) {
98100 mc .mu .Lock ()
99101 defer mc .mu .Unlock ()
100102
101- logger .Debug ().Str ("user_id" , string (userID )).Str ("since" , since ).Msg ("matrix: performing sync" )
103+ logger .Debug ().Str ("user_id" , string (userID )).Str ("since" , since ).Str ( "filter_after_event_id" , filterAfterEventID ). Msg ("matrix: performing sync" )
102104
103105 mc .cli .UserID = userID
104- // The SyncRequest method takes filter parameters directly in this version.
105- // Using empty filter to ensure we get all rooms and messages
106- resp , err := mc .cli .SyncRequest (ctx , 30000 , since , "" , false , event .PresenceOnline )
106+
107+ // Create a filter that only returns message events to optimize bandwidth
108+ filter := & mautrix.Filter {
109+ Room : & mautrix.RoomFilter {
110+ Timeline : & mautrix.FilterPart {
111+ Types : []event.Type {event .EventMessage },
112+ Limit : 100 , // Reasonable limit to get enough context
113+ },
114+ },
115+ }
116+
117+ // Marshal the filter to JSON string for the SyncRequest
118+ filterBytes , err := json .Marshal (filter )
119+ if err != nil {
120+ logger .Error ().Str ("user_id" , string (userID )).Err (err ).Msg ("matrix: failed to marshal filter" )
121+ return nil , fmt .Errorf ("marshal filter: %w" , err )
122+ }
123+ filterJSON := string (filterBytes )
124+ logger .Debug ().Str ("user_id" , string (userID )).Str ("filter" , filterJSON ).Msg ("matrix: using message filter for sync" )
125+
126+ // The SyncRequest method signature: SyncRequest(ctx, timeoutMS, since, filter, fullState, setPresence)
127+ resp , err := mc .cli .SyncRequest (ctx , 30000 , since , filterJSON , false , event .PresenceOnline )
107128 if err != nil {
108129 logger .Error ().Str ("user_id" , string (userID )).Err (err ).Msg ("matrix: sync failed" )
109130 return nil , err
110131 }
111132
133+ // Post-process: If filterAfterEventID is provided, filter room timelines to only include events after it
134+ // This is necessary because the Matrix spec doesn't support server-side filtering by event ID
135+ if filterAfterEventID != "" {
136+ logger .Debug ().Str ("user_id" , string (userID )).Str ("filter_after_event_id" , filterAfterEventID ).Msg ("matrix: filtering sync results by event ID" )
137+ for roomID , room := range resp .Rooms .Join {
138+ foundEvent := false
139+ // Find the index of the target event
140+ for j , evt := range room .Timeline .Events {
141+ if string (evt .ID ) == filterAfterEventID {
142+ // Keep only events after this one
143+ room .Timeline .Events = room .Timeline .Events [j + 1 :]
144+ resp .Rooms .Join [roomID ] = room
145+ logger .Debug ().Str ("user_id" , string (userID )).Str ("room_id" , roomID .String ()).Int ("events_removed" , j + 1 ).Msg ("matrix: filtered room timeline" )
146+ foundEvent = true
147+ break
148+ }
149+ }
150+ if ! foundEvent && len (room .Timeline .Events ) > 0 {
151+ // Event not found in this timeline window - the requested event is older than what we got
152+ // Keep all events since they're all newer than the requested event
153+ logger .Debug ().Str ("user_id" , string (userID )).Str ("room_id" , roomID .String ()).Msg ("matrix: filter event not found in timeline, keeping all events" )
154+ }
155+ }
156+ }
157+
112158 logger .Debug ().Str ("user_id" , string (userID )).Int ("rooms" , len (resp .Rooms .Join )).Msg ("matrix: sync completed" )
113159 return resp , nil
114160}
0 commit comments