about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--LibMatrix/Filters/SyncFilter.cs7
-rw-r--r--LibMatrix/Helpers/SyncProcessors/Msc4222EmulationSyncProcessor.cs87
2 files changed, 83 insertions, 11 deletions
diff --git a/LibMatrix/Filters/SyncFilter.cs b/LibMatrix/Filters/SyncFilter.cs

index 8c66656..7cb6428 100644 --- a/LibMatrix/Filters/SyncFilter.cs +++ b/LibMatrix/Filters/SyncFilter.cs
@@ -34,7 +34,7 @@ public class SyncFilter { [JsonPropertyName("include_leave")] public bool? IncludeLeave { get; set; } - private static readonly RoomFilter Empty = new() { + private static RoomFilter Empty => new() { Rooms = [], IncludeLeave = false, AccountData = StateFilter.Empty, @@ -75,7 +75,8 @@ public class SyncFilter { [JsonPropertyName("unread_thread_notifications")] public bool? UnreadThreadNotifications { get; set; } = unreadThreadNotifications; - public static readonly StateFilter Empty = new(limit: 0, senders: [], types: [], rooms: []); + // ReSharper disable once MemberHidesStaticFromOuterClass + public new static StateFilter Empty => new(limit: 0, senders: [], types: [], rooms: []); } } @@ -95,6 +96,6 @@ public class SyncFilter { [JsonPropertyName("not_senders")] public List<string>? NotSenders { get; set; } = notSenders; - public static readonly EventFilter Empty = new(limit: 0, senders: [], types: []); + public static EventFilter Empty => new(limit: 0, senders: [], types: []); } } diff --git a/LibMatrix/Helpers/SyncProcessors/Msc4222EmulationSyncProcessor.cs b/LibMatrix/Helpers/SyncProcessors/Msc4222EmulationSyncProcessor.cs
index b18a8e0..f9f6ba3 100644 --- a/LibMatrix/Helpers/SyncProcessors/Msc4222EmulationSyncProcessor.cs +++ b/LibMatrix/Helpers/SyncProcessors/Msc4222EmulationSyncProcessor.cs
@@ -7,7 +7,11 @@ namespace LibMatrix.Helpers.SyncProcessors; public class Msc4222EmulationSyncProcessor(AuthenticatedHomeserverGeneric homeserver) { private static bool StateEventsMatch(StateEventResponse a, StateEventResponse b) { - return a.Type == b.Type && a.StateKey == b.StateKey && a.OriginServerTs < b.OriginServerTs; + return a.Type == b.Type && a.StateKey == b.StateKey; + } + + private static bool StateEventIsNewer(StateEventResponse a, StateEventResponse b) { + return StateEventsMatch(a, b) && a.OriginServerTs < b.OriginServerTs; } public async Task<SyncResponse?> EmulateMsc4222(SyncResponse? resp) { @@ -40,7 +44,7 @@ public class Msc4222EmulationSyncProcessor(AuthenticatedHomeserverGeneric homese } Console.WriteLine($"Msc4222EmulationSyncProcessor.EmulateMsc4222 processed {resp.Rooms?.Join?.Count}/{resp.Rooms?.Leave?.Count} rooms in {sw.Elapsed}"); - if (modified) + if (modified) resp.Msc4222Method = SyncResponse.Msc4222SyncType.Emulated; return resp; @@ -48,14 +52,78 @@ public class Msc4222EmulationSyncProcessor(AuthenticatedHomeserverGeneric homese private async Task<bool> ProcessJoinedRooms(KeyValuePair<string, SyncResponse.RoomsDataStructure.JoinedRoomDataStructure> roomData) { var (roomId, data) = roomData; + var room = homeserver.GetRoom(roomId); if (data.StateAfter is { Events.Count: > 0 }) { return false; } - data.StateAfter = new() { }; + data.StateAfter = new() { Events = [] }; + + data.StateAfter = new() { + Events = [] + }; + + var oldState = new List<StateEventResponse>(); + if (data.State is { Events.Count: > 0 }) { + oldState.ReplaceBy(data.State.Events, StateEventIsNewer); + } + + if (data.Timeline is { Limited: true }) { + if (data.Timeline.Events != null) + oldState.ReplaceBy(data.Timeline.Events, StateEventIsNewer); + + try { + var timeline = await homeserver.GetRoom(roomId).GetMessagesAsync(limit: 250); + if (timeline is { State.Count: > 0 }) { + oldState.ReplaceBy(timeline.State, StateEventIsNewer); + } + + if (timeline is { Chunk.Count: > 0 }) { + oldState.ReplaceBy(timeline.Chunk.Where(x => x.StateKey != null), StateEventIsNewer); + } + } + catch (Exception e) { + Console.WriteLine($"Msc4222Emulation: Failed to get timeline for room {roomId}, state may be incomplete!\n{e}"); + } + } - return false; + oldState = oldState.DistinctBy(x => (x.Type, x.StateKey)).ToList(); + + // Different order: we need oldState here to reduce the set + try { + data.StateAfter.Events = (await room.GetFullStateAsListAsync()) + // .Where(x=> oldState.Any(y => StateEventsMatch(x, y))) + // .Join(oldState, x => (x.Type, x.StateKey), y => (y.Type, y.StateKey), (x, y) => x) + .IntersectBy(oldState.Select(s => (s.Type, s.StateKey)), s => (s.Type, s.StateKey)) + .ToList(); + + data.State = null; + return true; + } + catch (Exception e) { + Console.WriteLine($"Msc4222Emulation: Failed to get full state for room {roomId}, state may be incomplete!\n{e}"); + } + + var tasks = oldState + .Select(async oldEvt => { + try { + return await room.GetStateEventAsync(oldEvt.Type, oldEvt.StateKey!); + } + catch (Exception e) { + Console.WriteLine($"Msc4222Emulation: Failed to get state event {oldEvt.Type}/{oldEvt.StateKey} for room {roomId}, state may be incomplete!\n{e}"); + return oldEvt; + } + }); + + var tasksEnum = tasks.ToAsyncEnumerable(); + await foreach (var evt in tasksEnum) { + data.StateAfter.Events.Add(evt); + } + + data.State = null; + + return true; } private async Task<bool> ProcessLeftRooms(KeyValuePair<string, SyncResponse.RoomsDataStructure.LeftRoomDataStructure> roomData) { @@ -72,6 +140,7 @@ public class Msc4222EmulationSyncProcessor(AuthenticatedHomeserverGeneric homese try { data.StateAfter.Events = await room.GetFullStateAsListAsync(); + data.State = null; return true; } catch (Exception e) { @@ -80,21 +149,21 @@ public class Msc4222EmulationSyncProcessor(AuthenticatedHomeserverGeneric homese var oldState = new List<StateEventResponse>(); if (data.State is { Events.Count: > 0 }) { - oldState.ReplaceBy(data.State.Events, StateEventsMatch); + oldState.ReplaceBy(data.State.Events, StateEventIsNewer); } if (data.Timeline is { Limited: true }) { if (data.Timeline.Events != null) - oldState.ReplaceBy(data.Timeline.Events, StateEventsMatch); + oldState.ReplaceBy(data.Timeline.Events, StateEventIsNewer); try { var timeline = await homeserver.GetRoom(roomId).GetMessagesAsync(limit: 250); if (timeline is { State.Count: > 0 }) { - oldState.ReplaceBy(timeline.State, StateEventsMatch); + oldState.ReplaceBy(timeline.State, StateEventIsNewer); } if (timeline is { Chunk.Count: > 0 }) { - oldState.ReplaceBy(timeline.Chunk.Where(x => x.StateKey != null), StateEventsMatch); + oldState.ReplaceBy(timeline.Chunk.Where(x => x.StateKey != null), StateEventIsNewer); } } catch (Exception e) { @@ -120,6 +189,8 @@ public class Msc4222EmulationSyncProcessor(AuthenticatedHomeserverGeneric homese data.StateAfter.Events.Add(evt); } + data.State = null; + return true; } } \ No newline at end of file