From 83e6d98d2d7586fb518ed1b2097c59ea9b8af223 Mon Sep 17 00:00:00 2001 From: Rory& Date: Wed, 31 Jan 2024 12:10:03 +0100 Subject: New tools, fix room list items --- .../Pages/Tools/RoomIntersections.razor | 199 +++++++++++++++++++++ MatrixUtils.Web/Pages/Tools/SessionCount.razor | 155 ++++++++++++++++ MatrixUtils.Web/Pages/Tools/SpaceDebug.razor | 22 +-- MatrixUtils.Web/Pages/Tools/UserTrace.razor | 139 ++++++++++++++ MatrixUtils.Web/Pages/Tools/ViewAccountData.razor | 30 ++++ 5 files changed, 535 insertions(+), 10 deletions(-) create mode 100644 MatrixUtils.Web/Pages/Tools/RoomIntersections.razor create mode 100644 MatrixUtils.Web/Pages/Tools/SessionCount.razor create mode 100644 MatrixUtils.Web/Pages/Tools/UserTrace.razor create mode 100644 MatrixUtils.Web/Pages/Tools/ViewAccountData.razor (limited to 'MatrixUtils.Web/Pages/Tools') diff --git a/MatrixUtils.Web/Pages/Tools/RoomIntersections.razor b/MatrixUtils.Web/Pages/Tools/RoomIntersections.razor new file mode 100644 index 0000000..395f84c --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/RoomIntersections.razor @@ -0,0 +1,199 @@ +@page "/Tools/RoomIntersections" +@using ArcaneLibs.Extensions +@using LibMatrix.RoomTypes +@using System.Collections.ObjectModel +@using LibMatrix +@using System.Collections.Frozen +@using LibMatrix.EventTypes.Spec.State +

Room intersections

+
+ +

Set A:

+ +Append Set A + +

Set B:

+ +Append Set B +
+Execute +
+ +
+ Results +
+        @{
+            var userColWidth = matches.Count == 0 ? 0 : matches.Keys.Max(x => x.Length);
+        }
+        
+            @foreach (var (userId, sets) in matches) {
+                
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+                
+                @for (int i = 1; i < Math.Max(sets.Item1.Count, sets.Item2.Count); i++) {
+                    
+                        
+                            
+                            
+                            
+                        }
+                        else {
+                            
+                            
+                            
+                             
+                        }
+                        else {
+                            
+                }
+            }
+            
+        
@userId.PadRight(userColWidth + 5)@sets.Item1[0].Room.RoomId@((sets.Item1[0].Member.TypedContent as RoomMemberEventContent).Membership)@(roomNames.ContainsKey(sets.Item1[0].Room) ? roomNames[sets.Item1[0].Room] : "")@(roomAliasses.ContainsKey(sets.Item1[0].Room) ? roomAliasses[sets.Item1[0].Room] : "")@sets.Item2[0].Room.RoomId@((sets.Item2[0].Member.TypedContent as RoomMemberEventContent).Membership)@(roomNames.ContainsKey(sets.Item2[0].Room) ? roomNames[sets.Item2[0].Room] : "")@(roomAliasses.ContainsKey(sets.Item2[0].Room) ? roomAliasses[sets.Item2[0].Room] : "")
+ @if (sets.Item1.Count > i) { + @sets.Item1[i].Room.RoomId@((sets.Item1[i].Member.TypedContent as RoomMemberEventContent).Membership)@(roomNames.ContainsKey(sets.Item1[i].Room) ? roomNames[sets.Item1[i].Room] : "")@(roomAliasses.ContainsKey(sets.Item1[i].Room) ? roomAliasses[sets.Item1[i].Room] : "") + + + + } + @if (sets.Item2.Count > i) { + @sets.Item2[0].Room.RoomId@((sets.Item2[i].Member.TypedContent as RoomMemberEventContent).Membership)@(roomNames.ContainsKey(sets.Item2[i].Room) ? roomNames[sets.Item2[i].Room] : "")@(roomAliasses.ContainsKey(sets.Item2[i].Room) ? roomAliasses[sets.Item2[i].Room] : "") + + + + } +
+
+
+
+ +
+@foreach (var line in Log.Reverse()) { +
@line
+} + +@code { + private ObservableCollection Log { get; set; } = new(); + List RoomsA { get; set; } = new(); + List RoomsB { get; set; } = new(); + + [Parameter, SupplyParameterFromQuery(Name = "a")] + public string ImportSetASpaceId { get; set; } = ""; + + [Parameter, SupplyParameterFromQuery(Name = "b")] + public string ImportSetBSpaceId { get; set; } = ""; + + Dictionary> roomMembers { get; set; } = new(); + + Dictionary, List)> matches { get; set; } = new(); + + AuthenticatedHomeserverGeneric hs { get; set; } + + // private string RoomListAString { + // get => string.Join("\n", RoomIdsA); + // set => RoomIdsA = value.Split("\n").Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); + // } + // + // private string RoomListBString { + // get => string.Join("\n", RoomIdsB); + // set => RoomIdsB = value.Split("\n").Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); + // } + + // private List RoomIdsA { get; set; } = new(); + // private List RoomIdsB { get; set; } = new(); + + // room info + Dictionary roomNames { get; set; } = new(); + Dictionary roomAliasses { get; set; } = new(); + + protected override async Task OnInitializedAsync() { + Log.CollectionChanged += (sender, args) => StateHasChanged(); + hs = await RMUStorage.GetCurrentSessionOrNavigate(); + if (hs is null) return; + + StateHasChanged(); + Console.WriteLine("Rerendered!"); + await base.OnInitializedAsync(); + } + + private async Task Execute() { + // get all users which are in any room of both sets of rooms, and which rooms + var setAusers = new Dictionary>(); + var setBusers = new Dictionary>(); + + await Task.WhenAll(GetMembers(RoomsA, setAusers), GetMembers(RoomsB, setBusers)); + + Log.Add($"Got {setAusers.Count} users in set A"); + Log.Add($"Got {setBusers.Count} users in set B"); + Log.Add("Calculating intersections..."); + + // get all users which are in both sets of rooms + // var users = setAusers.Keys.Intersect(setBusers.Keys).ToList(); + // var groups = setAusers.IntersectBy(setBusers, (x,y) => x.Key).ToList(); + matches = setAusers.Keys.Intersect(setBusers.Keys).Select(x => (x, setAusers[x], setBusers[x])).ToDictionary(x => x.x, x => (x.Item2, x.Item3)); + + Log.Add($"Found {matches.Count} users in both sets of rooms"); + StateHasChanged(); + } + + public async Task GetMembers(List rooms, Dictionary> users) { + foreach (var room in rooms) { + Log.Add($"Getting members for {room.RoomId}"); + var members = await room.GetMembersListAsync(false); + foreach (var member in members) { + if (member.RawContent?["membership"]?.ToString() == "ban") continue; + if (member.RawContent?["membership"]?.ToString() == "invite") continue; + if (!users.ContainsKey(member.StateKey)) users[member.StateKey] = new(); + users[member.StateKey].Add(new() { + Room = room, + Member = member + }); + } + } + } + + public async Task AppendSet(string spaceId, List rooms) { + var space = hs.GetRoom(spaceId).AsSpace; + Log.Add($"Found space {spaceId}"); + var roomIdsEnum = space.GetChildrenAsync(true); + List tasks = new(); + await foreach (var room in roomIdsEnum) { + tasks.Add(loadRoomData(room, rooms)); + } + + await Task.WhenAll(tasks); + + async Task loadRoomData(GenericRoom room, List rooms) { + Log.Add($"Found room {room.RoomId}"); + try { + await room.GetPowerLevelsAsync(); + rooms.Add(room); + try { + roomAliasses[room] = (await room.GetCanonicalAliasAsync()).Alias; + } + catch { } + + try { + roomNames[room] = await room.GetNameOrFallbackAsync(); + } + catch { } + } + catch (MatrixException e) { + Log.Add($"Failed to get power levels for {room.RoomId}: {e.Message}"); + } + } + } + + public class Match { + public GenericRoom Room { get; set; } + public StateEventResponse Member { get; set; } + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/SessionCount.razor b/MatrixUtils.Web/Pages/Tools/SessionCount.razor new file mode 100644 index 0000000..3b68bfa --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/SessionCount.razor @@ -0,0 +1,155 @@ +@page "/Tools/SessionCount" +@using ArcaneLibs.Extensions +@using LibMatrix.RoomTypes +@using System.Collections.ObjectModel +@using LibMatrix +@using System.Collections.Frozen +@using LibMatrix.EventTypes.Spec.State +

User Trace

+
+ +

Users:

+ +
+Import from room (ID) + +
+ Rooms to be searched (@rooms.Count) + @foreach (var room in rooms) { + @room.RoomId +
+ } +
+
+Execute +
+ +
+ Results + @foreach (var (userId, events) in matches) { +

@userId

+
    + @foreach (var eventResponse in events) { +
  • @eventResponse.Room.RoomId
  • + } +
+ } +
+
+ Results text + @{ + var col1Width = matches.Keys.Max(x => x.Length); + } +
+        @foreach (var (userId, events) in matches) {
+            

+ @userId.PadRight(col1Width) + @foreach (var @event in events) { + +} +

+ } +
+
+ +
+@foreach (var line in log.Reverse()) { +
@line
+} + +@code { + private ObservableCollection log { get; set; } = new(); + List hss { get; set; } = new(); + ObservableCollection rooms { get; set; } = new(); + Dictionary> roomMembers { get; set; } = new(); + Dictionary> matches = new(); + + private string UserIdString { + get => string.Join("\n", UserIDs); + set => UserIDs = value.Split("\n").Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); + } + + private List UserIDs { get; set; } = new(); + + protected override async Task OnInitializedAsync() { + log.CollectionChanged += (sender, args) => StateHasChanged(); + var hs = await RMUStorage.GetCurrentSessionOrNavigate(); + if (hs is null) return; + rooms.CollectionChanged += (sender, args) => StateHasChanged(); + var sessions = await RMUStorage.GetAllTokens(); + foreach (var userAuth in sessions) { + var session = await RMUStorage.GetSession(userAuth); + if (session is not null) { + var sessionRooms = await session.GetJoinedRooms(); + foreach (var room in sessionRooms) { + rooms.Add(room); + } + + StateHasChanged(); + log.Add($"Got {sessionRooms.Count} rooms for {userAuth.UserId}"); + } + } + + log.Add("Done fetching rooms!"); + + var distinctRooms = rooms.DistinctBy(x => x.RoomId).ToArray(); + Random.Shared.Shuffle(distinctRooms); + rooms = new ObservableCollection(distinctRooms); + rooms.CollectionChanged += (sender, args) => StateHasChanged(); + + var stateTasks = rooms.Select(async x => (x, await x.GetMembersListAsync(false))).ToAsyncEnumerable(); + + await foreach (var (room, state) in stateTasks) { + roomMembers.Add(room, state); + log.Add($"Got {state.Count} members for {room.RoomId}..."); + } + + log.Add($"Done fetching members!"); + + UserIDs.RemoveAll(x => sessions.Any(y => y.UserId == x)); + + StateHasChanged(); + Console.WriteLine("Rerendered!"); + await base.OnInitializedAsync(); + } + + private async Task Execute() { + foreach (var userId in UserIDs) { + matches.Add(userId, new List()); + foreach (var (room, events) in roomMembers) { + if (events.Any(x => x.Type == RoomMemberEventContent.EventId && x.StateKey == userId)) { + matches[userId].Add(new() { + Event = events.First(x => x.StateKey == userId && x.Type == RoomMemberEventContent.EventId), + Room = room, + }); + } + } + } + + return ""; + } + + public string? ImportFromRoomId { get; set; } + + private async Task DoImportFromRoomId() { + try { + if (ImportFromRoomId is null) return; + var room = rooms.FirstOrDefault(x => x.RoomId == ImportFromRoomId); + UserIdString = string.Join("\n", (await room.GetMembersListAsync()).Select(x => x.StateKey)); + } + catch (Exception e) { + Console.WriteLine(e); + log.Add("Could not fetch members list!\n" + e.ToString()); + } + + StateHasChanged(); + } + + private class Matches { + public GenericRoom Room; + + public StateEventResponse Event; + // public + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor b/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor index 5d9b8eb..09e5b12 100644 --- a/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor +++ b/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor @@ -1,6 +1,7 @@ @page "/Tools/SpaceDebug" @using LibMatrix.Filters @using LibMatrix.Helpers +@using LibMatrix.Utilities

SpaceDebug


@@ -49,16 +50,17 @@ if (hs is null) return; var syncHelper = new SyncHelper(hs) { - Filter = new SyncFilter() { - Presence = new(0), - Room = new() { - AccountData = new(limit: 0), - Ephemeral = new(limit: 0), - State = new(limit: 1000, types: new() { "m.space.child", "m.space.parent" }), - Timeline = new(limit: 0) - }, - AccountData = new(limit: 0) - } + // Filter = new SyncFilter() { + // Presence = new(0), + // Room = new() { + // AccountData = new(limit: 0), + // Ephemeral = new(limit: 0), + // State = new(limit: 1000, types: new() { "m.space.child", "m.space.parent" }), + // Timeline = new(limit: 0) + // }, + // AccountData = new(limit: 0) + // } + NamedFilterName = CommonSyncFilters.GetSpaceRelations }; Status = "Syncing..."; diff --git a/MatrixUtils.Web/Pages/Tools/UserTrace.razor b/MatrixUtils.Web/Pages/Tools/UserTrace.razor new file mode 100644 index 0000000..b3a7487 --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/UserTrace.razor @@ -0,0 +1,139 @@ +@page "/Tools/UserTrace" +@using ArcaneLibs.Extensions +@using LibMatrix.RoomTypes +@using System.Collections.ObjectModel +@using LibMatrix +@using System.Collections.Frozen +@using LibMatrix.EventTypes.Spec.State +

User Trace

+
+ +

Users:

+ +
+Import from room (ID) + +
+ Rooms to be searched (@rooms.Count) + @foreach (var room in rooms) { + @room.RoomId +
+ } +
+
+Execute +
+ +
+ Results + @foreach (var (userId, events) in matches) { +

@userId

+
    + @foreach (var eventResponse in events) { +
  • @eventResponse.Room.RoomId
  • + } +
+ } +
+ +
+@foreach (var line in log.Reverse()) { +
@line
+} + +@code { + private ObservableCollection log { get; set; } = new(); + List hss { get; set; } = new(); + ObservableCollection rooms { get; set; } = new(); + Dictionary> roomMembers { get; set; } = new(); + Dictionary> matches = new(); + + private string UserIdString { + get => string.Join("\n", UserIDs); + set => UserIDs = value.Split("\n").Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); + } + + private List UserIDs { get; set; } = new(); + + protected override async Task OnInitializedAsync() { + log.CollectionChanged += (sender, args) => StateHasChanged(); + var hs = await RMUStorage.GetCurrentSessionOrNavigate(); + if (hs is null) return; + rooms.CollectionChanged += (sender, args) => StateHasChanged(); + var sessions = await RMUStorage.GetAllTokens(); + foreach (var userAuth in sessions) { + var session = await RMUStorage.GetSession(userAuth); + if (session is not null) { + var sessionRooms = await session.GetJoinedRooms(); + foreach (var room in sessionRooms) { + rooms.Add(room); + } + + StateHasChanged(); + log.Add($"Got {sessionRooms.Count} rooms for {userAuth.UserId}"); + } + } + + log.Add("Done fetching rooms!"); + + var distinctRooms = rooms.DistinctBy(x => x.RoomId).ToArray(); + Random.Shared.Shuffle(distinctRooms); + rooms = new ObservableCollection(distinctRooms); + rooms.CollectionChanged += (sender, args) => StateHasChanged(); + + var stateTasks = rooms.Select(async x => (x, await x.GetMembersListAsync(false))).ToAsyncEnumerable(); + + await foreach (var (room, state) in stateTasks) { + roomMembers.Add(room, state); + log.Add($"Got {state.Count} members for {room.RoomId}..."); + } + + log.Add($"Done fetching members!"); + + UserIDs.RemoveAll(x=>sessions.Any(y=>y.UserId == x)); + + StateHasChanged(); + Console.WriteLine("Rerendered!"); + await base.OnInitializedAsync(); + } + + private async Task Execute() { + foreach (var userId in UserIDs) { + matches.Add(userId, new List()); + foreach (var (room, events) in roomMembers) { + if (events.Any(x => x.Type == RoomMemberEventContent.EventId && x.StateKey == userId)) { + matches[userId].Add(new() { + Event = events.First(x => x.StateKey == userId && x.Type == RoomMemberEventContent.EventId), + Room = room, + + }); + } + } + } + + return ""; + } + + public string? ImportFromRoomId { get; set; } + + private async Task DoImportFromRoomId() { + try { + if (ImportFromRoomId is null) return; + var room = rooms.FirstOrDefault(x => x.RoomId == ImportFromRoomId); + UserIdString = string.Join("\n", (await room.GetMembersListAsync()).Select(x => x.StateKey)); + } + catch (Exception e) { + Console.WriteLine(e); + log.Add("Could not fetch members list!\n" + e.ToString()); + } + + StateHasChanged(); + } + + private class Matches { + public GenericRoom Room; + public StateEventResponse Event; + // public + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/ViewAccountData.razor b/MatrixUtils.Web/Pages/Tools/ViewAccountData.razor new file mode 100644 index 0000000..398c7ce --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/ViewAccountData.razor @@ -0,0 +1,30 @@ +@page "/Tools/ViewAccountData" +@using ArcaneLibs.Extensions +@using LibMatrix +@using LibMatrix.Filters +@using LibMatrix.Helpers +@using LibMatrix.Utilities +

View account data

+
+
@globalAccountData?.Events.ToJson(ignoreNull: true)
+
+ +@foreach (var (key, value) in perRoomAccountData) { + @key

+
@value?.Events.ToJson(ignoreNull: true)
+} + +@code { + EventList? globalAccountData; + Dictionary perRoomAccountData = new(); + + protected override async Task OnInitializedAsync() { + var hs = await RMUStorage.GetCurrentSessionOrNavigate(); + if (hs is null) return; + perRoomAccountData = await hs.EnumerateAccountDataPerRoom(); + globalAccountData = await hs.EnumerateAccountData(); + + StateHasChanged(); + } + +} \ No newline at end of file -- cgit 1.5.1