about summary refs log tree commit diff
diff options
context:
space:
mode:
m---------LibMatrix0
-rw-r--r--MatrixUtils.Abstractions/RoomInfo.cs1
-rw-r--r--MatrixUtils.LibDMSpace/DMSpaceRoom.cs1
-rw-r--r--MatrixUtils.Web/Classes/RMUStorageWrapper.cs13
-rw-r--r--MatrixUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs1
-rw-r--r--MatrixUtils.Web/MatrixUtils.Web.csproj5
-rw-r--r--MatrixUtils.Web/Pages/Index.razor28
-rw-r--r--MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage1.razor1
-rw-r--r--MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage2.razor1
-rw-r--r--MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage3.razor1
-rw-r--r--MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor1
-rw-r--r--MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2SyncContainer.razor1
-rw-r--r--MatrixUtils.Web/Pages/Moderation/UserRoomHistory.razor1
-rw-r--r--MatrixUtils.Web/Pages/Rooms/Create.razor1
-rw-r--r--MatrixUtils.Web/Pages/Rooms/PolicyList.razor1
-rw-r--r--MatrixUtils.Web/Pages/Rooms/PolicyList2.razor1
-rw-r--r--MatrixUtils.Web/Pages/Rooms/Timeline.razor1
-rw-r--r--MatrixUtils.Web/Pages/StreamTest.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/InviteCounter.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectedRoomsEditor.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectionsEditor.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirWatchedListsEditor.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/FindUsersByRegex.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor672
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor6
-rw-r--r--MatrixUtils.Web/Pages/Tools/Room/SpaceRestrictedJoins.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor1
-rw-r--r--MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor1
-rw-r--r--MatrixUtils.Web/Pages/User/DMManager.razor1
-rw-r--r--MatrixUtils.Web/Pages/User/Profile.razor1
-rw-r--r--MatrixUtils.Web/Shared/InlineUserItem.razor1
-rw-r--r--MatrixUtils.Web/Shared/RoomListItem.razor1
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor1
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor1
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor1
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor1
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor1
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor1
-rw-r--r--MatrixUtils.sln6
-rwxr-xr-xscripts/deploy.sh1
43 files changed, 524 insertions, 242 deletions
diff --git a/LibMatrix b/LibMatrix
-Subproject cc61a7ae65d427e862e67ed92ec39f449cb2334
+Subproject 040c244d35ff42b59993c85a5110d4e7aedc023
diff --git a/MatrixUtils.Abstractions/RoomInfo.cs b/MatrixUtils.Abstractions/RoomInfo.cs

index aff0e25..81ce388 100644 --- a/MatrixUtils.Abstractions/RoomInfo.cs +++ b/MatrixUtils.Abstractions/RoomInfo.cs
@@ -3,7 +3,6 @@ using System.Collections.ObjectModel; using System.Text.Json.Nodes; using ArcaneLibs; using LibMatrix; -using LibMatrix.EventTypes.Spec.State; using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.Homeservers; using LibMatrix.RoomTypes; diff --git a/MatrixUtils.LibDMSpace/DMSpaceRoom.cs b/MatrixUtils.LibDMSpace/DMSpaceRoom.cs
index 55a7812..646a3f3 100644 --- a/MatrixUtils.LibDMSpace/DMSpaceRoom.cs +++ b/MatrixUtils.LibDMSpace/DMSpaceRoom.cs
@@ -1,6 +1,5 @@ using ArcaneLibs.Extensions; using LibMatrix; -using LibMatrix.EventTypes.Spec.State; using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.Homeservers; using LibMatrix.Responses; diff --git a/MatrixUtils.Web/Classes/RMUStorageWrapper.cs b/MatrixUtils.Web/Classes/RMUStorageWrapper.cs
index 45028ba..337c7e4 100644 --- a/MatrixUtils.Web/Classes/RMUStorageWrapper.cs +++ b/MatrixUtils.Web/Classes/RMUStorageWrapper.cs
@@ -47,12 +47,21 @@ public class RMUStorageWrapper(ILogger<RMUStorageWrapper> logger, TieredStorageS return null; } - return await homeserverProviderService.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy); + return await GetSession(token); } public async Task<AuthenticatedHomeserverGeneric?> GetSession(UserAuth userAuth) { logger.LogTrace("Getting session."); - return await homeserverProviderService.GetAuthenticatedWithToken(userAuth.Homeserver, userAuth.AccessToken, userAuth.Proxy); + AuthenticatedHomeserverGeneric hs; + try { + hs = await homeserverProviderService.GetAuthenticatedWithToken(userAuth.Homeserver, userAuth.AccessToken, userAuth.Proxy); + } + catch (Exception e) { + logger.LogError("Failed to get info for {0} via {1}: {2}", userAuth.UserId, userAuth.Homeserver, e); + logger.LogError("Continuing with server-less session"); + hs = await homeserverProviderService.GetAuthenticatedWithToken(userAuth.Homeserver, userAuth.AccessToken, userAuth.Proxy, useGeneric: true, enableServer: false); + } + return hs; } public async Task<AuthenticatedHomeserverGeneric?> GetCurrentSessionOrNavigate() { diff --git a/MatrixUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs b/MatrixUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
index 75d9e16..7078308 100644 --- a/MatrixUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs +++ b/MatrixUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
@@ -1,6 +1,5 @@ using System.Text.Json.Nodes; using LibMatrix; -using LibMatrix.EventTypes.Spec.State; using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.Responses; diff --git a/MatrixUtils.Web/MatrixUtils.Web.csproj b/MatrixUtils.Web/MatrixUtils.Web.csproj
index 93e30d9..b472b45 100644 --- a/MatrixUtils.Web/MatrixUtils.Web.csproj +++ b/MatrixUtils.Web/MatrixUtils.Web.csproj
@@ -51,8 +51,9 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="ArcaneLibs.Blazor.Components" Version="1.0.0-preview.20241210-161342" Condition="'$(Configuration)' == 'Release'"/> - <ProjectReference Include="..\LibMatrix\ArcaneLibs\ArcaneLibs.Blazor.Components\ArcaneLibs.Blazor.Components.csproj" Condition="'$(Configuration)' == 'Debug'"/> +<!-- <PackageReference Include="ArcaneLibs.Blazor.Components" Version="1.0.0-preview.20241210-161342" Condition="'$(Configuration)' == 'Release'"/>--> +<!-- <ProjectReference Include="..\LibMatrix\ArcaneLibs\ArcaneLibs.Blazor.Components\ArcaneLibs.Blazor.Components.csproj" Condition="'$(Configuration)' == 'Debug'"/>--> + <ProjectReference Include="..\LibMatrix\ArcaneLibs\ArcaneLibs.Blazor.Components\ArcaneLibs.Blazor.Components.csproj"/> </ItemGroup> <ItemGroup> diff --git a/MatrixUtils.Web/Pages/Index.razor b/MatrixUtils.Web/Pages/Index.razor
index 34f2e9b..8847467 100644 --- a/MatrixUtils.Web/Pages/Index.razor +++ b/MatrixUtils.Web/Pages/Index.razor
@@ -35,11 +35,13 @@ Small collection of tools to do not-so-everyday things. </td> <td class="user-info"> <p> - <input type="radio" name="csa" checked="@(_currentSession.AccessToken == auth.AccessToken)" @onclick="@(() => SwitchSession(auth))" style="text-decoration-line: unset;"/> + <input type="radio" name="csa" checked="@(_currentSession.AccessToken == auth.AccessToken)" @onclick="@(() => SwitchSession(auth))" + style="text-decoration-line: unset;"/> <b>@session.UserInfo.DisplayName</b> on <b>@auth.Homeserver</b><br/> </p> <span style="display: inline-block; width: 128px;">@session.UserInfo.RoomCount rooms</span> - <a style="color: #888888" href="@("/ServerInfo/" + session.Homeserver?.ServerName + "/")">@session.ServerVersion?.Server.Name @session.ServerVersion?.Server.Version</a> + <a style="color: #888888" + href="@("/ServerInfo/" + session.Homeserver?.ServerName + "/")">@session.ServerVersion?.Server.Name @session.ServerVersion?.Server.Version</a> @if (auth.Proxy != null) { <span class="badge badge-info"> (proxied via @auth.Proxy)</span> } @@ -114,7 +116,7 @@ Small collection of tools to do not-so-everyday things. </p> </td> <td> - <LinkButton OnClick="@(() => Task.Run(()=>NavigationManager.NavigateTo($"/InvalidSession?ctx={session.AccessToken}")))">Re-login</LinkButton> + <LinkButton OnClick="@(() => Task.Run(() => NavigationManager.NavigateTo($"/InvalidSession?ctx={session.AccessToken}")))">Re-login</LinkButton> </td> <td> <LinkButton OnClick="@(() => RemoveUser(session))">Remove</LinkButton> @@ -172,13 +174,27 @@ Small collection of tools to do not-so-everyday things. var updateSw = Stopwatch.StartNew(); var tasks = tokens.Select(async token => { await sema.WaitAsync(); - + AuthenticatedHomeserverGeneric hs; try { - hs = await HsProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy); + Task<ServerVersionResponse> serverVersionTask = Task.FromResult<ServerVersionResponse>(new() { + Server = new() { + Name = "Unknown", + Version = "0.0.0" + } + }); + try { + hs = await HsProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy); + serverVersionTask = hs.FederationClient?.GetServerVersionAsync() ?? serverVersionTask!; + } + catch (Exception e) { + logger.LogError("Failed to get info for {0} via {1}: {2}", token.UserId, token.Homeserver, e); + logger.LogError("Continuing with server-less session"); + hs = await HsProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy, useGeneric: true, enableServer: false); + } + var joinedRoomsTask = hs.GetJoinedRooms(); var profileTask = hs.GetProfileAsync(hs.WhoAmI.UserId); - var serverVersionTask = hs.FederationClient?.GetServerVersionAsync(); _sessions.Add(new() { UserInfo = new() { AvatarUrl = (await profileTask).AvatarUrl, diff --git a/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage1.razor b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage1.razor
index f147b5b..a974a8f 100644 --- a/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage1.razor +++ b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage1.razor
@@ -4,7 +4,6 @@ @using MatrixUtils.LibDMSpace @using MatrixUtils.LibDMSpace.StateEvents @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.EventTypes.Spec.State.Space @using MatrixUtils.Abstractions diff --git a/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage2.razor b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage2.razor
index 5a0bbd1..b8eb257 100644 --- a/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage2.razor +++ b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage2.razor
@@ -1,5 +1,4 @@ @using LibMatrix.RoomTypes -@using LibMatrix.EventTypes.Spec.State @using ArcaneLibs.Extensions @using LibMatrix.EventTypes.Spec.State.RoomInfo @using MatrixUtils.Abstractions diff --git a/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage3.razor b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage3.razor
index 6cba639..dac9c49 100644 --- a/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage3.razor +++ b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage3.razor
@@ -1,5 +1,4 @@ @using LibMatrix.RoomTypes -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.Responses @using MatrixUtils.LibDMSpace @using System.Text.Json.Serialization diff --git a/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor
index a8409fd..6bf542f 100644 --- a/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor +++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor
@@ -1,6 +1,5 @@ @using MatrixUtils.Abstractions @using System.ComponentModel -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.Space @using MatrixUtils.Web.Pages.Labs.Rooms2.Index2Components.MainTabComponents <h3>RoomsIndex2MainTab</h3> diff --git a/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2SyncContainer.razor b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2SyncContainer.razor
index 7a412c1..ae57521 100644 --- a/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2SyncContainer.razor +++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2SyncContainer.razor
@@ -2,7 +2,6 @@ @using LibMatrix.Responses @using MatrixUtils.Abstractions @using System.Diagnostics -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.Extensions @using LibMatrix.Utilities @using System.Collections.ObjectModel diff --git a/MatrixUtils.Web/Pages/Moderation/UserRoomHistory.razor b/MatrixUtils.Web/Pages/Moderation/UserRoomHistory.razor
index 1450a3d..9bb20f0 100644 --- a/MatrixUtils.Web/Pages/Moderation/UserRoomHistory.razor +++ b/MatrixUtils.Web/Pages/Moderation/UserRoomHistory.razor
@@ -1,5 +1,4 @@ @page "/Moderation/UserRoomHistory/{UserId}" -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.RoomTypes @using ArcaneLibs.Extensions @using LibMatrix.EventTypes.Spec.State.RoomInfo diff --git a/MatrixUtils.Web/Pages/Rooms/Create.razor b/MatrixUtils.Web/Pages/Rooms/Create.razor
index 0c476d7..a36ccf8 100644 --- a/MatrixUtils.Web/Pages/Rooms/Create.razor +++ b/MatrixUtils.Web/Pages/Rooms/Create.razor
@@ -3,7 +3,6 @@ @using System.Reflection @using ArcaneLibs.Extensions @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses @using MatrixUtils.Web.Classes.RoomCreationTemplates diff --git a/MatrixUtils.Web/Pages/Rooms/PolicyList.razor b/MatrixUtils.Web/Pages/Rooms/PolicyList.razor
index 0022213..34d5880 100644 --- a/MatrixUtils.Web/Pages/Rooms/PolicyList.razor +++ b/MatrixUtils.Web/Pages/Rooms/PolicyList.razor
@@ -1,7 +1,6 @@ @page "/Rooms/{RoomId}/Policies" @using LibMatrix @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.Policy @using System.Diagnostics @using LibMatrix.RoomTypes diff --git a/MatrixUtils.Web/Pages/Rooms/PolicyList2.razor b/MatrixUtils.Web/Pages/Rooms/PolicyList2.razor
index eed57e6..50f304a 100644 --- a/MatrixUtils.Web/Pages/Rooms/PolicyList2.razor +++ b/MatrixUtils.Web/Pages/Rooms/PolicyList2.razor
@@ -1,7 +1,6 @@ @page "/Rooms/{RoomId}/Policies2" @using LibMatrix @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.Policy @using System.Diagnostics @using LibMatrix.RoomTypes diff --git a/MatrixUtils.Web/Pages/Rooms/Timeline.razor b/MatrixUtils.Web/Pages/Rooms/Timeline.razor
index a5c88e8..a064956 100644 --- a/MatrixUtils.Web/Pages/Rooms/Timeline.razor +++ b/MatrixUtils.Web/Pages/Rooms/Timeline.razor
@@ -2,7 +2,6 @@ @using MatrixUtils.Web.Shared.TimelineComponents @using LibMatrix @using LibMatrix.EventTypes.Spec -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo <h3>RoomManagerTimeline</h3> <hr/> diff --git a/MatrixUtils.Web/Pages/StreamTest.razor b/MatrixUtils.Web/Pages/StreamTest.razor
index a70e872..4cec354 100644 --- a/MatrixUtils.Web/Pages/StreamTest.razor +++ b/MatrixUtils.Web/Pages/StreamTest.razor
@@ -1,7 +1,6 @@ @page "/StreamTest" @inject ILogger<Index> logger @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo <PageTitle>StreamText</PageTitle> diff --git a/MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor b/MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor
index 710bb2a..1adb440 100644 --- a/MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor +++ b/MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor
@@ -4,7 +4,6 @@ @using System.Collections.ObjectModel @using LibMatrix @using System.Collections.Frozen -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo <h3>User Trace</h3> <hr/> diff --git a/MatrixUtils.Web/Pages/Tools/InviteCounter.razor b/MatrixUtils.Web/Pages/Tools/InviteCounter.razor
index c9491d4..e2a0393 100644 --- a/MatrixUtils.Web/Pages/Tools/InviteCounter.razor +++ b/MatrixUtils.Web/Pages/Tools/InviteCounter.razor
@@ -1,6 +1,5 @@ @page "/Tools/InviteCounter" @using System.Collections.ObjectModel -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo <h3>User Trace</h3> <hr/> diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectedRoomsEditor.razor b/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectedRoomsEditor.razor
index 215ead3..953a1e6 100644 --- a/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectedRoomsEditor.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectedRoomsEditor.razor
@@ -3,7 +3,6 @@ @page "/Tools/Moderation/Draupnir/ProtectedRoomsEditor" @using LibMatrix @using LibMatrix.EventTypes.Interop.Draupnir -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.RoomTypes <h3>Edit Draupnir protected rooms</h3> diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectionsEditor.razor b/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectionsEditor.razor
index da84def..b4a9d35 100644 --- a/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectionsEditor.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirProtectionsEditor.razor
@@ -1,7 +1,6 @@ @page "/Tools/Moderation/Draupnir/ProtectionsEditor" @using System.Text.Json.Serialization @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.RoomTypes <h3>Edit Draupnir protected rooms</h3> diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirWatchedListsEditor.razor b/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirWatchedListsEditor.razor
index 4aa0d2f..1384a2a 100644 --- a/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirWatchedListsEditor.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/Draupnir/DraupnirWatchedListsEditor.razor
@@ -1,7 +1,6 @@ @page "/Tools/Moderation/Draupnir/WatchedListsEditor" @using System.Text.Json.Serialization @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.RoomTypes <h3>Edit Draupnir protected rooms</h3> diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/FindUsersByRegex.razor b/MatrixUtils.Web/Pages/Tools/Moderation/FindUsersByRegex.razor
index 24bc6e1..4b2af68 100644 --- a/MatrixUtils.Web/Pages/Tools/Moderation/FindUsersByRegex.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/FindUsersByRegex.razor
@@ -5,7 +5,6 @@ @using System.Collections.ObjectModel @using System.Text.RegularExpressions @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Filters @using LibMatrix.Helpers diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor b/MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor
index e7c5a7f..ea47237 100644 --- a/MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor
@@ -1,6 +1,5 @@ @page "/Tools/Moderation/InviteCounter" @using System.Collections.ObjectModel -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo <h3>Invite counter</h3> <hr/> diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor b/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor
index 82ae072..6b5b5e4 100644 --- a/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor
@@ -1,32 +1,159 @@ @page "/Tools/Moderation/MembershipHistory" +@using System.Collections.Frozen @using System.Collections.ObjectModel +@using System.Diagnostics @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo +@{ + var sw = Stopwatch.StartNew(); + Console.WriteLine("Start render"); +} <h3>Membership history viewer</h3> <hr/> - <br/> <span>Room ID: </span> -<InputText @bind-Value="@roomId"></InputText> +<InputText @bind-Value="@RoomId"></InputText> <LinkButton OnClick="@Execute">Execute</LinkButton> -<p><InputCheckbox @bind-Value="ChronologicalOrder"/> Chronological order</p> +<p> + <span><InputCheckbox @bind-Value="ChronologicalOrder"/>Chronological order</span> + <span><InputCheckbox @bind-Value="DoDisambiguate"/>Enable extended filters</span> +</p> <p> <span>Show </span> - <InputCheckbox @bind-Value="ShowJoins"/> joins - <InputCheckbox @bind-Value="ShowLeaves"/> leaves - <InputCheckbox @bind-Value="ShowUpdates"/> profile updates - <InputCheckbox @bind-Value="ShowKnocks"/> knocks - <InputCheckbox @bind-Value="ShowInvites"/> invites - <InputCheckbox @bind-Value="ShowKicks"/> kicks - <InputCheckbox @bind-Value="ShowBans"/> bans + <span><InputCheckbox @bind-Value="ShowJoins"/> joins</span> + <span><InputCheckbox @bind-Value="ShowLeaves"/> leaves</span> + <span><InputCheckbox @bind-Value="ShowKnocks"/> knocks</span> + <span><InputCheckbox @bind-Value="ShowInvites"/> invites</span> + <span><InputCheckbox @bind-Value="ShowBans"/> bans</span> </p> <p> - <LinkButton OnClick="@(async () => { ShowJoins = ShowLeaves = ShowUpdates = ShowKnocks = ShowInvites = ShowKicks = ShowBans = false; })">Hide all</LinkButton> - <LinkButton OnClick="@(async () => { ShowJoins = ShowLeaves = ShowUpdates = ShowKnocks = ShowInvites = ShowKicks = ShowBans = true; })">Show all</LinkButton> - <LinkButton OnClick="@(async () => { ShowJoins ^= true; ShowLeaves ^= true; ShowUpdates ^= true; ShowKnocks ^= true; ShowInvites ^= true; ShowKicks ^= true; ShowBans ^= true; })">Toggle all</LinkButton> + <LinkButton OnClick="@(async () => { + ShowJoins = ShowLeaves = ShowKnocks = ShowInvites = ShowBans = false; + StateHasChanged(); + })">Hide all + </LinkButton> + <LinkButton OnClick="@(async () => { + ShowJoins = ShowLeaves = ShowKnocks = ShowInvites = ShowBans = true; + StateHasChanged(); + })">Show all + </LinkButton> + <LinkButton OnClick="@(async () => { + ShowJoins ^= true; + ShowLeaves ^= true; + ShowKnocks ^= true; + ShowInvites ^= true; + ShowBans ^= true; + StateHasChanged(); + })">Toggle all + </LinkButton> </p> <p> + <span><InputCheckbox @bind-Value="DoDisambiguate"/> Disambiguate </span> + @if (DoDisambiguate) { + <span><InputCheckbox @bind-Value="DisambiguateKicks"/> kicks</span> + <span><InputCheckbox @bind-Value="DisambiguateUnbans"/> unbans</span> + <span><InputCheckbox @bind-Value="DisambiguateProfileUpdates"/> profile updates</span> + <details style="display: inline-block; vertical-align: top;"> + <summary> + <InputCheckbox @bind-Value="DisambiguateInviteActions"/> + invite actions + </summary> + <span><InputCheckbox @bind-Value="DisambiguateInviteAccepted"/> accepted</span> + <span><InputCheckbox @bind-Value="DisambiguateInviteRejected"/> rejected</span> + <span><InputCheckbox @bind-Value="DisambiguateInviteRetracted"/> retracted</span> + </details> + <details style="display: inline-block; vertical-align: top;"> + <summary> + <InputCheckbox @bind-Value="DisambiguateKnockActions"/> + knock actions + </summary> + <span><InputCheckbox @bind-Value="DisambiguateKnockAccepted"/> accepted</span> + <span><InputCheckbox @bind-Value="DisambiguateKnockRejected"/> rejected</span> + <span><InputCheckbox @bind-Value="DisambiguateKnockRetracted"/> retracted</span> + </details> + } +</p> +@if (DoDisambiguate) { + <p> + <span>Show </span> + @if (DisambiguateKicks) { + <span><InputCheckbox @bind-Value="ShowKicks"/> kicks</span> + } + @if (DisambiguateUnbans) { + <span><InputCheckbox @bind-Value="ShowUnbans"/> unbans</span> + } + @if (DisambiguateProfileUpdates) { + <span><InputCheckbox @bind-Value="ShowProfileUpdates"/> profile updates</span> + } + @if (DisambiguateInviteActions) { + <details style="display: inline-block; vertical-align: top;"> + <summary> + <InputCheckbox @bind-Value="ShowInviteActions"/> + invite actions + </summary> + @if (DisambiguateInviteAccepted) { + <span><InputCheckbox @bind-Value="ShowInviteAccepted"/> accepted</span> + } + + @if (DisambiguateInviteRejected) { + <span><InputCheckbox @bind-Value="ShowInviteRejected"/> rejected</span> + } + + @if (DisambiguateInviteRetracted) { + <span><InputCheckbox @bind-Value="ShowInviteRetracted"/> retracted</span> + } + </details> + } + @if (DisambiguateKnockActions) { + <details style="display: inline-block; vertical-align: top;"> + <summary> + <InputCheckbox @bind-Value="ShowKnockActions"/> + knock actions + </summary> + @if (DisambiguateKnockAccepted) { + <span><InputCheckbox @bind-Value="ShowKnockAccepted"/> accepted</span> + } + + @if (DisambiguateKnockRejected) { + <span><InputCheckbox @bind-Value="ShowKnockRejected"/> rejected</span> + } + + @if (DisambiguateKnockRetracted) { + <span><InputCheckbox @bind-Value="ShowKnockRetracted"/> retracted</span> + } + </details> + } + </p> + + <p> + <LinkButton OnClick="@(async () => { + DoDisambiguate = DisambiguateProfileUpdates = DisambiguateKicks = DisambiguateUnbans = DisambiguateInviteAccepted = DisambiguateInviteRejected = DisambiguateInviteRetracted = DisambiguateKnockAccepted = DisambiguateKnockRejected = DisambiguateKnockRetracted = DisambiguateKnockActions = DisambiguateInviteActions = false; + StateHasChanged(); + })">Un-disambiguate all + </LinkButton> + <LinkButton OnClick="@(async () => { + DoDisambiguate = DisambiguateProfileUpdates = DisambiguateKicks = DisambiguateUnbans = DisambiguateInviteAccepted = DisambiguateInviteRejected = DisambiguateInviteRetracted = DisambiguateKnockAccepted = DisambiguateKnockRejected = DisambiguateKnockRetracted = DisambiguateKnockActions = DisambiguateInviteActions = true; + StateHasChanged(); + })">Disambiguate all + </LinkButton> + <LinkButton OnClick="@(async () => { + DisambiguateProfileUpdates ^= true; + DisambiguateKicks ^= true; + DisambiguateUnbans ^= true; + DisambiguateInviteAccepted ^= true; + DisambiguateInviteRejected ^= true; + DisambiguateInviteRetracted ^= true; + DisambiguateKnockAccepted ^= true; + DisambiguateKnockRejected ^= true; + DisambiguateKnockRetracted ^= true; + DisambiguateKnockActions ^= true; + DisambiguateInviteActions ^= true; + StateHasChanged(); + })">Toggle all + </LinkButton> + </p> +} +<p> <span>Sender: </span> <InputSelect @bind-Value="Sender"> <option value="">All</option> @@ -45,109 +172,121 @@ </InputSelect> </p> - +@{ Console.WriteLine($"Rendering took {sw.Elapsed} for {Memberships.Count} items"); } <br/> -<details> +<details open> <summary>Results</summary> @{ - Dictionary<string, StateEventResponse> previousMemberships = []; - var filteredMemberships = Memberships.AsEnumerable(); - if (ChronologicalOrder) { - filteredMemberships = filteredMemberships.Reverse(); - } - - if (!string.IsNullOrWhiteSpace(Sender)) { - filteredMemberships = filteredMemberships.Where(x => x.Sender == Sender); - } - - if (!string.IsNullOrWhiteSpace(User)) { - filteredMemberships = filteredMemberships.Where(x => x.StateKey == User); - } - + var filteredMemberships = GetFilteredMemberships(); + } <table> - @foreach (var membership in filteredMemberships) { - RoomMemberEventContent content = membership.TypedContent as RoomMemberEventContent; - StateEventResponse? previous = previousMemberships.GetValueOrDefault(membership.StateKey); - RoomMemberEventContent? previousContent = previous?.TypedContent as RoomMemberEventContent; + @foreach (var membershipEntry in filteredMemberships) { + var (transition, membership, previousMembership) = membershipEntry; + RoomMemberEventContent content = membership.TypedContent as RoomMemberEventContent ?? throw new InvalidOperationException("Event is not a RoomMemberEventContent!"); + RoomMemberEventContent? previousContent = previousMembership?.TypedContent as RoomMemberEventContent; + <tr> <td>@DateTimeOffset.FromUnixTimeMilliseconds(membership.OriginServerTs ?? 0).ToString("g")</td> <td> - @switch (content.Membership) { - case RoomMemberEventContent.MembershipTypes.Invite: { - if (_showInvites) { - <p style="color: green;">@membership.Sender invited @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p> - } - + @switch (transition) { + case MembershipTransition.None: + <b>Unknown membership! Got None</b> break; - } - case RoomMemberEventContent.MembershipTypes.Ban: { - if (_showBans) { - <p style="color: red;">@membership.Sender banned @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p> - } - + case MembershipTransition.Join: + <p style="color: #6C6;"> + @membership.StateKey joined the room @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")<br/> + Display name: @content.DisplayName<br/> + Avatar URL: @content.AvatarUrl + </p> break; - } - case RoomMemberEventContent.MembershipTypes.Leave: { - if (membership.Sender == membership.StateKey) { - if (_showLeaves) { - <p style="color: #C66;">@membership.Sender left the room</p> - } - } - else { - if (_showKicks) { - <p style="color: darkorange;">@membership.Sender kicked @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p> - } - } - + case MembershipTransition.Leave: + <p style="color: #C66;"> + @membership.StateKey left the room + </p> break; - } - case RoomMemberEventContent.MembershipTypes.Knock: { - if (_showKnocks) { - <p>@membership.Sender knocked @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p> - } - + case MembershipTransition.Knock: + <p style="color: #426"> + @membership.StateKey knocked @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})") + </p> break; - } - case RoomMemberEventContent.MembershipTypes.Join: { - if (previousContent is { Membership: RoomMemberEventContent.MembershipTypes.Join }) { - if (_showUpdates) { - <p style="color: #777;"> - @membership.Sender changed their profile<br/> - Display name: @previousContent.DisplayName -> @content.DisplayName<br/> - Avatar URL: @previousContent.AvatarUrl -> @content.AvatarUrl - </p> - } - } - else { - if (_showJoins) { - <p style="color: #6C6;"> - @membership.Sender joined the room @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")<br/> - Display name: @content.DisplayName<br/> - Avatar URL: @content.AvatarUrl - </p> - } - } - + case MembershipTransition.Invite: + <p style="color: #262;"> + @membership.Sender invited @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})") + </p> + break; + case MembershipTransition.Ban: + <p style="color: red;"> + @membership.Sender banned @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})") + </p> + break; + @* disambiguated *@ + case MembershipTransition.Kick: + <p style="color: darkorange;"> + @membership.Sender kicked @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})") + </p> + break; + case MembershipTransition.ProfileUpdate: + <p style="color: #777;"> + @membership.Sender changed their profile<br/> + Display name: @previousContent!.DisplayName -> @content.DisplayName<br/> + Avatar URL: @previousContent.AvatarUrl -> @content.AvatarUrl + </p> + break; + case MembershipTransition.InviteAccepted: + <p style="color: #084;"> + @membership.StateKey accepted the invite + from @previousMembership!.Sender @(string.IsNullOrWhiteSpace(previousContent?.Reason) ? "" : $"(invite reason: {previousContent.Reason})") @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(accept reason: {content.Reason})") + </p> break; - } - default: { - <b>Unknown membership @content.Membership!</b> + case MembershipTransition.KnockAccepted: + <p style="color: #288;"> + @membership.StateKey's knock was accepted + by @previousMembership!.Sender @(string.IsNullOrWhiteSpace(previousContent?.Reason) ? "" : $"(knock reason: {previousContent.Reason})") @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(accept reason: {content.Reason})") + </p> break; - } + case MembershipTransition.KnockRejected: + <p style="color: #828;"> + @membership.StateKey's knock was rejected + by @previousMembership!.Sender @(string.IsNullOrWhiteSpace(previousContent?.Reason) ? "" : $"(knock reason: {previousContent.Reason})") @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reject reason: {content.Reason})") + </p> + break; + case MembershipTransition.Unban: + <p style="color: #0C0;"> + @membership.Sender unbanned @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})") + </p> + break; + case MembershipTransition.InviteRejected: + <p style="color: #733;"> + @membership.StateKey rejected the invite + from @previousMembership!.Sender @(string.IsNullOrWhiteSpace(previousContent?.Reason) ? "" : $"(invite reason: {previousContent.Reason})") @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reject reason: {content.Reason})") + </p> + break; + case MembershipTransition.InviteRetracted: + <p style="color: #844;"> + @membership.Sender retracted the invite + for @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})") + </p> + break; + case MembershipTransition.KnockRetracted: + <p style="color: #b55;"> + @membership.Sender retracted the knock + for @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})") + </p> + break; + default: + throw new ArgumentOutOfRangeException(); } </td> </tr> - - previousMemberships[membership.StateKey] = membership; } - </table>} + </table> </details> <br/> <details open> <summary>Log</summary> - @foreach (var line in log.Reverse()) { + @foreach (var line in Log.Reverse()) { <pre>@line</pre> } </details> @@ -156,139 +295,280 @@ #region Filter bindings - private bool _chronologicalOrder; + private bool ChronologicalOrder { get; set; } + private bool ShowJoins { get; set; } = true; + private bool ShowLeaves { get; set; } = true; + private bool ShowKnocks { get; set; } = true; + private bool ShowInvites { get; set; } = true; + private bool ShowBans { get; set; } = true; + + private bool DoDisambiguate { get; set; } = true; + private bool DisambiguateProfileUpdates { get => field && DoDisambiguate; set; } = true; + private bool DisambiguateKicks { get => field && DoDisambiguate; set; } = true; + private bool DisambiguateUnbans { get => field && DoDisambiguate; set; } = true; + private bool DisambiguateInviteAccepted { get => field && DoDisambiguate && DisambiguateInviteActions; set; } = true; + private bool DisambiguateInviteRejected { get => field && DoDisambiguate && DisambiguateInviteActions; set; } = true; + private bool DisambiguateInviteRetracted { get => field && DoDisambiguate && DisambiguateInviteActions; set; } = true; + private bool DisambiguateKnockAccepted { get => field && DoDisambiguate && DisambiguateKnockActions; set; } = true; + private bool DisambiguateKnockRejected { get => field && DoDisambiguate && DisambiguateKnockActions; set; } = true; + private bool DisambiguateKnockRetracted { get => field && DoDisambiguate && DisambiguateKnockActions; set; } = true; + + private bool DisambiguateKnockActions { get => field && DoDisambiguate; set; } = true; + private bool DisambiguateInviteActions { get => field && DoDisambiguate; set; } = true; + + private bool ShowProfileUpdates { + get => field && DisambiguateProfileUpdates; + set; + } = true; - private bool ChronologicalOrder { - get => _chronologicalOrder; + private bool ShowKicks { + get => field && DisambiguateKicks; + set; + } = true; + + private bool ShowUnbans { + get => field && DisambiguateUnbans; + set; + } = true; + + private bool ShowInviteAccepted { + get => field && DisambiguateInviteAccepted; + set; + } = true; + + private bool ShowInviteRejected { + get => field && DisambiguateInviteRejected; + set; + } = true; + + private bool ShowInviteRetracted { + get => field && DisambiguateInviteRetracted; + set; + } = true; + + private bool ShowKnockAccepted { + get => field && DisambiguateKnockAccepted; + set; + } = true; + + private bool ShowKnockRejected { + get => field && DisambiguateKnockRejected; + set; + } = true; + + private bool ShowKnockRetracted { + get => field && DisambiguateKnockRetracted; + set; + } = true; + + private bool ShowKnockActions { + get => field && DisambiguateKnockActions; + set; + } = true; + + private bool ShowInviteActions { + get => field && DisambiguateInviteActions; + set; + } = true; + + [Parameter, SupplyParameterFromQuery(Name = "sender")] + public string Sender { get; set; } = ""; + + [Parameter, SupplyParameterFromQuery(Name = "user")] + public string User { get; set; } = ""; + + [Parameter, SupplyParameterFromQuery(Name = "filter")] + public string Filter { + get; set { - _chronologicalOrder = value; + field = value; + if (string.IsNullOrWhiteSpace(value)) return; + var parts = value.Split(','); + ShowJoins = parts.Contains("join"); + ShowLeaves = parts.Contains("leave"); + ShowKnocks = parts.Contains("knock"); + ShowInvites = parts.Contains("invite"); + ShowBans = parts.Contains("ban"); StateHasChanged(); } - } - - private bool _showJoins = true; + } = ""; - private bool ShowJoins { - get => _showJoins; - set { - _showJoins = value; - StateHasChanged(); - } - } +#endregion - private bool _showLeaves = true; + private ObservableCollection<string> Log { get; set; } = new(); + private List<StateEventResponse> Memberships { get; set; } = []; + private AuthenticatedHomeserverGeneric Homeserver { get; set; } = null!; - private bool ShowLeaves { - get => _showLeaves; - set { - _showLeaves = value; - StateHasChanged(); - } - } + [Parameter, SupplyParameterFromQuery(Name = "room")] + public string RoomId { get; set; } = ""; - private bool _showUpdates = true; + protected override async Task OnInitializedAsync() { + Log.CollectionChanged += (sender, args) => StateHasChanged(); + Homeserver = await RmuStorage.GetCurrentSessionOrNavigate(); + if (Homeserver is null) return; - private bool ShowUpdates { - get => _showUpdates; - set { - _showUpdates = value; - StateHasChanged(); - } + StateHasChanged(); + Console.WriteLine("Rerendered!"); + await base.OnInitializedAsync(); + if (!string.IsNullOrWhiteSpace(RoomId)) + await Execute(); } - private bool _showKnocks = true; + private async Task Execute() { + Memberships.Clear(); + var room = Homeserver.GetRoom(RoomId); + var events = room.GetManyMessagesAsync(limit: int.MaxValue, chunkSize: 5000); + await foreach (var resp in events) { + var all = resp.State.Concat(resp.Chunk); + Memberships.AddRange(all.Where(x => x.Type == RoomMemberEventContent.EventId)); - private bool ShowKnocks { - get => _showKnocks; - set { - _showKnocks = value; - StateHasChanged(); + Log.Add($"Got {resp.State.Count} state and {resp.Chunk.Count} timeline events."); } - } - private bool _showInvites = true; + Log.Add("Reached end of timeline!"); - private bool ShowInvites { - get => _showInvites; - set { - _showInvites = value; - StateHasChanged(); - } + StateHasChanged(); } - private bool _showKicks = true; + private readonly struct MembershipEntry { + public required MembershipTransition State { get; init; } + public required StateEventResponse Event { get; init; } + public required StateEventResponse? Previous { get; init; } - private bool ShowKicks { - get => _showKicks; - set { - _showKicks = value; - StateHasChanged(); + public void Deconstruct(out MembershipTransition transition, out StateEventResponse evt, out StateEventResponse? prev) { + transition = State; + evt = Event; + prev = Previous; } } - private bool _showBans = true; - - private bool ShowBans { - get => _showBans; - set { - _showBans = value; - StateHasChanged(); - } + private enum MembershipTransition : byte { + None, + Join, + Leave, + Knock, + Invite, + Ban, + + // disambiguated + ProfileUpdate, + Kick, + Unban, + InviteAccepted, + InviteRejected, + InviteRetracted, + KnockAccepted, + KnockRejected, + KnockRetracted } - private string sender = ""; - - private string Sender { - get => sender; - set { - sender = value; - StateHasChanged(); + private static IEnumerable<MembershipEntry> GetTransitions(List<StateEventResponse> evts) { + Dictionary<string, MembershipEntry> transitions = new(); + foreach (var evt in evts.OrderBy(x => x.OriginServerTs)) { + var content = evt.TypedContent as RoomMemberEventContent ?? throw new InvalidOperationException("Event is not a RoomMemberEventContent!"); + var prev = transitions.GetValueOrDefault(evt.StateKey!) as MembershipEntry?; + transitions[evt.StateKey ?? throw new Exception("Member event has no state key??")] = new MembershipEntry { + Event = evt, + Previous = prev?.Event, + State = content.Membership switch { + RoomMemberEventContent.MembershipTypes.Join => + prev?.State switch { + MembershipTransition.Join or MembershipTransition.InviteAccepted => MembershipTransition.ProfileUpdate, + MembershipTransition.Invite => MembershipTransition.InviteAccepted, + _ => MembershipTransition.Join + }, + RoomMemberEventContent.MembershipTypes.Leave => + evt.Sender == evt.StateKey + ? prev?.State switch { + MembershipTransition.Knock => MembershipTransition.KnockRetracted, + MembershipTransition.Invite => MembershipTransition.InviteRejected, + _ => MembershipTransition.Leave + } + : prev?.State switch { + // not self + MembershipTransition.Knock => MembershipTransition.KnockRejected, + MembershipTransition.Invite => MembershipTransition.InviteRetracted, + _ => MembershipTransition.Kick, + }, + RoomMemberEventContent.MembershipTypes.Invite => + prev?.State switch { + MembershipTransition.Knock => MembershipTransition.KnockAccepted, + _ => MembershipTransition.Invite + }, + RoomMemberEventContent.MembershipTypes.Knock => MembershipTransition.Knock, + RoomMemberEventContent.MembershipTypes.Ban => MembershipTransition.Ban, + _ => MembershipTransition.None + } + }; + yield return transitions[evt.StateKey]; } } - private string user = ""; - - private string User { - get => user; - set { - user = value; - StateHasChanged(); + private IEnumerable<MembershipEntry> Disambiguated(IEnumerable<MembershipEntry> entries) { + FrozenDictionary<MembershipTransition, MembershipTransition> disambiguated = new Dictionary<MembershipTransition, MembershipTransition>() { + { MembershipTransition.ProfileUpdate, MembershipTransition.Join }, + { MembershipTransition.Kick, MembershipTransition.Leave }, + { MembershipTransition.Unban, MembershipTransition.Leave }, + { MembershipTransition.InviteAccepted, MembershipTransition.Join }, + { MembershipTransition.InviteRejected, MembershipTransition.Leave }, + { MembershipTransition.InviteRetracted, MembershipTransition.Leave }, + { MembershipTransition.KnockAccepted, MembershipTransition.Invite }, + { MembershipTransition.KnockRejected, MembershipTransition.Leave }, + { MembershipTransition.KnockRetracted, MembershipTransition.Leave } + }.ToFrozenDictionary(); + + foreach (var entry in entries) { + if (!DoDisambiguate) { + yield return entry; + continue; + } + + var newState = entry.State switch { + MembershipTransition.ProfileUpdate when !DoDisambiguate || !DisambiguateProfileUpdates => MembershipTransition.Join, + MembershipTransition.Kick when !DoDisambiguate || !DisambiguateKicks => MembershipTransition.Leave, + MembershipTransition.Unban when !DoDisambiguate || !DisambiguateUnbans => MembershipTransition.Leave, + MembershipTransition.InviteAccepted when !DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteAccepted => MembershipTransition.Join, + MembershipTransition.InviteRejected when !DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteRejected => MembershipTransition.Leave, + MembershipTransition.InviteRetracted when !DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteRetracted => MembershipTransition.Leave, + MembershipTransition.KnockAccepted when !DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockAccepted => MembershipTransition.Invite, + MembershipTransition.KnockRejected when !DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockRejected => MembershipTransition.Leave, + MembershipTransition.KnockRetracted when !DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockRetracted => MembershipTransition.Leave, + _ => entry.State + }; + if (newState != entry.State) { + yield return entry with { State = newState }; + } + else yield return entry; } } -#endregion - - private ObservableCollection<string> log { get; set; } = new(); - private List<StateEventResponse> Memberships { get; set; } = []; - private AuthenticatedHomeserverGeneric hs { get; set; } - - [Parameter, SupplyParameterFromQuery(Name = "room")] - public string roomId { get; set; } - - 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(); - if (!string.IsNullOrWhiteSpace(roomId)) - await Execute(); - } - - private async Task Execute() { - Memberships.Clear(); - var room = hs.GetRoom(roomId); - var events = room.GetManyMessagesAsync(limit: int.MaxValue, chunkSize: 5000); - await foreach (var resp in events) { - var all = resp.State.Concat(resp.Chunk); - Memberships.AddRange(all.Where(x => x.Type == RoomMemberEventContent.EventId)); - - log.Add($"{resp.State.Count} state, {resp.Chunk.Count} timeline"); + private IEnumerable<MembershipEntry> GetFilteredMemberships() { + var filteredMemberships = GetTransitions(Memberships); + if (!string.IsNullOrWhiteSpace(Sender)) filteredMemberships = filteredMemberships.Where(x => x.Event.Sender == Sender); + if (!string.IsNullOrWhiteSpace(User)) filteredMemberships = filteredMemberships.Where(x => x.Event.StateKey == User); + filteredMemberships = Disambiguated(filteredMemberships); + + if (!ShowJoins) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.Join); + if (!ShowLeaves) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.Leave); + if (!ShowKnocks) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.Knock); + if (!ShowInvites) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.Invite); + if (!ShowBans) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.Ban); + // extended filters + if (DoDisambiguate) { + if (!DisambiguateProfileUpdates || !ShowProfileUpdates) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.ProfileUpdate); + if (!DisambiguateKicks || !ShowKicks) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.Kick); + if (!DisambiguateUnbans || !ShowUnbans) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.Unban); + if (!DisambiguateInviteActions || !ShowInviteActions || !DisambiguateInviteAccepted || !ShowInviteAccepted) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.InviteAccepted); + if (!DisambiguateInviteActions || !ShowInviteActions || !DisambiguateInviteRejected || !ShowInviteRejected) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.InviteRejected); + if (!DisambiguateInviteActions || !ShowInviteActions || !DisambiguateInviteRetracted || !ShowInviteRetracted) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.InviteRetracted); + if (!DisambiguateKnockActions || !ShowKnockActions || !DisambiguateKnockAccepted || !ShowKnockAccepted) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.KnockAccepted); + if (!DisambiguateKnockActions || !ShowKnockActions || !DisambiguateKnockRejected || !ShowKnockRejected) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.KnockRejected); + if (!DisambiguateKnockActions || !ShowKnockActions || !DisambiguateKnockRetracted || !ShowKnockRetracted) filteredMemberships = filteredMemberships.Where(x => x.State != MembershipTransition.KnockRetracted); } - StateHasChanged(); + if (!ChronologicalOrder) filteredMemberships = filteredMemberships.Reverse(); + + return filteredMemberships; } } \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor b/MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor
index 8516ea8..15eea15 100644 --- a/MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor
@@ -2,7 +2,6 @@ @using LibMatrix.RoomTypes @using System.Collections.ObjectModel @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo <h3>Room intersections</h3> <hr/> diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor b/MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor
index 3768da4..0d622cc 100644 --- a/MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor
@@ -3,7 +3,6 @@ @using LibMatrix.RoomTypes @using System.Collections.ObjectModel @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo <h3>User Trace</h3> <hr/> @@ -184,5 +183,10 @@ { Membership: "ban", Reason: not null } => $"Banned by {state.Sender} at {time} for {membership.Reason}", }; } + + private async Task ExportJson() { + var json = matches.ToJson(); + + } } \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/Room/SpaceRestrictedJoins.razor b/MatrixUtils.Web/Pages/Tools/Room/SpaceRestrictedJoins.razor
index d9a7d1d..b57810a 100644 --- a/MatrixUtils.Web/Pages/Tools/Room/SpaceRestrictedJoins.razor +++ b/MatrixUtils.Web/Pages/Tools/Room/SpaceRestrictedJoins.razor
@@ -1,6 +1,5 @@ @page "/Tools/Room/SpaceRestrictedJoins" @using System.Collections.ObjectModel -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo <h3>Allow space to restricted join children</h3> <hr/> diff --git a/MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor b/MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor
index 5e8c265..64dbfcf 100644 --- a/MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor +++ b/MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor
@@ -1,7 +1,6 @@ @page "/Tools/CopyPowerlevel" @using ArcaneLibs.Extensions @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.RoomTypes <h3>Copy powerlevel</h3> diff --git a/MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor b/MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor
index 76558ea..e352c91 100644 --- a/MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor +++ b/MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor
@@ -1,7 +1,6 @@ @page "/Tools/MassRoomJoin" @using ArcaneLibs.Extensions @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo <h3>Mass join room</h3> <hr/> diff --git a/MatrixUtils.Web/Pages/User/DMManager.razor b/MatrixUtils.Web/Pages/User/DMManager.razor
index 4a6e5b4..fe45eb8 100644 --- a/MatrixUtils.Web/Pages/User/DMManager.razor +++ b/MatrixUtils.Web/Pages/User/DMManager.razor
@@ -1,5 +1,4 @@ @page "/User/DirectMessages" -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.Responses @using MatrixUtils.Abstractions @using LibMatrix diff --git a/MatrixUtils.Web/Pages/User/Profile.razor b/MatrixUtils.Web/Pages/User/Profile.razor
index f7ec080..d0af2c8 100644 --- a/MatrixUtils.Web/Pages/User/Profile.razor +++ b/MatrixUtils.Web/Pages/User/Profile.razor
@@ -1,5 +1,4 @@ @page "/User/Profile" -@using LibMatrix.EventTypes.Spec.State @using LibMatrix @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses diff --git a/MatrixUtils.Web/Shared/InlineUserItem.razor b/MatrixUtils.Web/Shared/InlineUserItem.razor
index 5b6d42f..50fa9e1 100644 --- a/MatrixUtils.Web/Shared/InlineUserItem.razor +++ b/MatrixUtils.Web/Shared/InlineUserItem.razor
@@ -1,4 +1,3 @@ -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses <div style="background-color: #ffffff11; border-radius: 0.5em; height: 1em; display: inline-block; vertical-align: middle;" alt="@UserId"> diff --git a/MatrixUtils.Web/Shared/RoomListItem.razor b/MatrixUtils.Web/Shared/RoomListItem.razor
index 1875f1d..d75d159 100644 --- a/MatrixUtils.Web/Shared/RoomListItem.razor +++ b/MatrixUtils.Web/Shared/RoomListItem.razor
@@ -1,5 +1,4 @@ @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses @using MatrixUtils.Abstractions diff --git a/MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor
index 80b9ac5..f107eb3 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor
@@ -1,5 +1,4 @@ @using LibMatrix -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses <h3>BaseTimelineItem</h3> diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor
index 74087a5..5d09603 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor
@@ -1,5 +1,4 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @inherits BaseTimelineItem diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
index a5ffe80..e5a5650 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
@@ -1,5 +1,4 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses @inherits BaseTimelineItem diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor
index 4459be1..98b5a6d 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor
@@ -1,6 +1,5 @@ @using ArcaneLibs.Extensions @using LibMatrix.EventTypes.Spec -@using LibMatrix.EventTypes.Spec.State.RoomInfo @inherits BaseTimelineItem <span> diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor
index 57dc77d..c342c83 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor
@@ -1,5 +1,4 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @inherits BaseTimelineItem diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor
index 6779b5d..467c644 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor
@@ -1,5 +1,4 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.RoomInfo @inherits BaseTimelineItem diff --git a/MatrixUtils.sln b/MatrixUtils.sln
index e4193c2..5fb0c1f 100644 --- a/MatrixUtils.sln +++ b/MatrixUtils.sln
@@ -65,6 +65,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MxApiExtensions.Classes", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MxApiExtensions", "MxApiExtensions\MxApiExtensions\MxApiExtensions.csproj", "{44BFB1AD-62FB-4B5B-A5A8-E7D04D731684}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{CEECE820-1BA9-4E29-8668-25967B3E712B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -179,6 +181,10 @@ Global {44BFB1AD-62FB-4B5B-A5A8-E7D04D731684}.Debug|Any CPU.Build.0 = Debug|Any CPU {44BFB1AD-62FB-4B5B-A5A8-E7D04D731684}.Release|Any CPU.ActiveCfg = Release|Any CPU {44BFB1AD-62FB-4B5B-A5A8-E7D04D731684}.Release|Any CPU.Build.0 = Release|Any CPU + {CEECE820-1BA9-4E29-8668-25967B3E712B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CEECE820-1BA9-4E29-8668-25967B3E712B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CEECE820-1BA9-4E29-8668-25967B3E712B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CEECE820-1BA9-4E29-8668-25967B3E712B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {84BE90C4-2FDE-4A48-B154-58926EF24846} = {933DC8A6-8B1F-46BF-9046-4B636AA46469} diff --git a/scripts/deploy.sh b/scripts/deploy.sh
index d0b7bb4..7c5086f 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh
@@ -11,4 +11,5 @@ BASE_DIR=`pwd` rm -rf **/bin/Release cd MatrixUtils.Web dotnet publish -c Release +dotnet restore # restore debug deps rsync --delete -raP bin/Release/net9.0/publish/wwwroot/ rory.gay:/data/nginx/html_mru/