about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2025-02-08 21:08:22 +0100
committerRory& <root@rory.gay>2025-02-08 21:08:22 +0100
commite8196ca2e7532cccae2fdecce3dff14294f66750 (patch)
tree8f0f051c42b59ae2060d48ae759236f724a81994
parentUpdate ArcaneLibs to fix modal windows (diff)
downloadMatrixUtils-e8196ca2e7532cccae2fdecce3dff14294f66750.tar.xz
Various changes
-rw-r--r--.idea/.idea.MatrixUtils/.idea/inspectionProfiles/Project_Default.xml31
-rw-r--r--Benchmarks/.gitignore3
-rw-r--r--Benchmarks/Benchmarks.csproj17
-rw-r--r--Benchmarks/Program.cs300
m---------LibMatrix0
-rw-r--r--MatrixUtils.Web/Classes/Constants/RoomConstants.cs5
-rw-r--r--MatrixUtils.Web/Classes/RMUStorageWrapper.cs4
-rw-r--r--MatrixUtils.Web/Pages/Rooms/PolicyList.razor4
-rw-r--r--MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor46
-rw-r--r--MatrixUtils.Web/Pages/Tools/InviteCounter.razor22
-rw-r--r--MatrixUtils.Web/Properties/launchSettings.json2
-rw-r--r--MatrixUtils.Web/Shared/MainLayout.razor2
12 files changed, 413 insertions, 23 deletions
diff --git a/.idea/.idea.MatrixUtils/.idea/inspectionProfiles/Project_Default.xml b/.idea/.idea.MatrixUtils/.idea/inspectionProfiles/Project_Default.xml

index 55540ea..0e61b0a 100644 --- a/.idea/.idea.MatrixUtils/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/.idea.MatrixUtils/.idea/inspectionProfiles/Project_Default.xml
@@ -17,6 +17,37 @@ </option> <option name="myCustomValuesEnabled" value="true" /> </inspection_tool> + <inspection_tool class="HttpUrlsUsage" enabled="true" level="WEAK WARNING" enabled_by_default="true"> + <option name="ignoredUrls"> + <list> + <option value="http://" /> + <option value="http://0.0.0.0" /> + <option value="http://127.0.0.1" /> + <option value="http://activemq.apache.org/schema/" /> + <option value="http://cxf.apache.org/schemas/" /> + <option value="http://java.sun.com/" /> + <option value="http://javafx.com/fxml" /> + <option value="http://javafx.com/javafx/" /> + <option value="http://json-schema.org/draft" /> + <option value="http://localhost" /> + <option value="http://maven.apache.org/POM/" /> + <option value="http://maven.apache.org/xsd/" /> + <option value="http://primefaces.org/ui" /> + <option value="http://schema.cloudfoundry.org/spring/" /> + <option value="http://schemas.xmlsoap.org/" /> + <option value="http://tiles.apache.org/" /> + <option value="http://www.ibm.com/webservices/xsd" /> + <option value="http://www.jboss.com/xml/ns/" /> + <option value="http://www.jboss.org/j2ee/schema/" /> + <option value="http://www.springframework.org/schema/" /> + <option value="http://www.springframework.org/security/tags" /> + <option value="http://www.springframework.org/tags" /> + <option value="http://www.thymeleaf.org" /> + <option value="http://www.w3.org/" /> + <option value="http://xmlns.jcp.org/" /> + </list> + </option> + </inspection_tool> <inspection_tool class="JsonStandardCompliance" enabled="false" level="ERROR" enabled_by_default="false" /> </profile> </component> \ No newline at end of file diff --git a/Benchmarks/.gitignore b/Benchmarks/.gitignore new file mode 100644
index 0000000..a7d52bf --- /dev/null +++ b/Benchmarks/.gitignore
@@ -0,0 +1,3 @@ + +BenchmarkDotNet.Artifacts +benchmark.log diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj new file mode 100644
index 0000000..5d584c9 --- /dev/null +++ b/Benchmarks/Benchmarks.csproj
@@ -0,0 +1,17 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>net9.0</TargetFramework> + <LangVersion>preview</LangVersion> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> +<!-- <PublishAot>true</PublishAot>--> + <InvariantGlobalization>true</InvariantGlobalization> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="BenchmarkDotNet" Version="0.14.0" /> + </ItemGroup> + +</Project> diff --git a/Benchmarks/Program.cs b/Benchmarks/Program.cs new file mode 100644
index 0000000..b85fc24 --- /dev/null +++ b/Benchmarks/Program.cs
@@ -0,0 +1,300 @@ +// See https://aka.ms/new-console-template for more information + +using System.Collections.Frozen; +using System.Collections.Immutable; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Engines; +using BenchmarkDotNet.Running; + +[SimpleJob(RunStrategy.ColdStart, launchCount: 1, warmupCount: 5, iterationCount: 5, id: "FastAndDirtyJob")] +[InProcess] +[ProcessCount(4)] +public class Program { + public static void Main(string[] args) { + BenchmarkRunner.Run<Program>(args: args); + } + + [Params(true, false)] + public bool DoDisambiguate { get; set; } = true; + + [Params(true, false)] + public bool DisambiguateProfileUpdates { + get => field && DoDisambiguate; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateKicks { + get => field && DoDisambiguate; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateUnbans { + get => field && DoDisambiguate; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateInviteAccepted { + get => field && DoDisambiguate && DisambiguateInviteActions; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateInviteRejected { + get => field && DoDisambiguate && DisambiguateInviteActions; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateInviteRetracted { + get => field && DoDisambiguate && DisambiguateInviteActions; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateKnockAccepted { + get => field && DoDisambiguate && DisambiguateKnockActions; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateKnockRejected { + get => field && DoDisambiguate && DisambiguateKnockActions; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateKnockRetracted { + get => field && DoDisambiguate && DisambiguateKnockActions; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateKnockActions { + get => field && DoDisambiguate; + set; + } = true; + + [Params(true, false)] + public bool DisambiguateInviteActions { + get => field && DoDisambiguate; + set; + } = true; + + public enum MembershipTransition : uint { + None, + Join = 0b0001, + Leave = 0b0010, + Knock = 0b0100, + Invite = 0b1000, + Ban = 0b1001, + + // disambiguated + ProfileUpdate = 0b0000_0001_0001, + Kick = 0b0000_0001_0010, + Unban = 0b0000_0010_0010, + InviteAccepted = 0b0000_0100_0001, + InviteRejected = 0b0000_1000_0010, + InviteRetracted = 0b0001_0000_0010, + KnockAccepted = 0b0010_0000_1000, + KnockRejected = 0b0100_0000_0010, + KnockRetracted = 0b1000_0000_0010 + } + + public readonly struct MembershipEntry { + public required MembershipTransition State { get; init; } + public string Aba { get; init; } + public string Abb { get; init; } + public string Abc { get; init; } + public string Abd { get; init; } + } + + [Params(100, 10_000, 1_000_000)] public int N; + + [GlobalSetup] + public void Setup() { + entries = Enumerable.Range(0, N).Select(_ => new MembershipEntry() { + State = (MembershipTransition)new Random().Next(1, 16), + Aba = Guid.NewGuid().ToString(), + Abb = Guid.NewGuid().ToString(), + Abc = Guid.NewGuid().ToString(), + Abd = Guid.NewGuid().ToString() + }).ToImmutableList(); + } + + public ImmutableList<MembershipEntry> entries = ImmutableList<MembershipEntry>.Empty; + + [Benchmark] + public void TestTruthyness() { + var @switch = AmbiguateMembershipsSwitch().GetEnumerator(); + var @switchpm = AmbiguateMembershipsSwitchPatternMatching().GetEnumerator(); + var @if = AmbiguateMembershipsIf().GetEnumerator(); + var @map = AmbiguateMembershipsStaticMap().GetEnumerator(); + var @binmask = AmbiguateMembershipsBinMask().GetEnumerator(); + + while (@switch.MoveNext() && @map.MoveNext() && @if.MoveNext() && @switchpm.MoveNext() && @binmask.MoveNext()) { + if (@switch.Current.State != @map.Current.State || @switch.Current.State != @if.Current.State || @switch.Current.State != @switchpm.Current.State || + @switch.Current.State != @binmask.Current.State) { + throw new InvalidOperationException("Results do not match!"); + } + } + + @switch.Dispose(); + @switchpm.Dispose(); + @if.Dispose(); + @map.Dispose(); + @binmask.Dispose(); + } + + [Benchmark] + public void TestAmbiguateMembershipsSwitchPatternMatching() => AmbiguateMembershipsSwitchPatternMatching().Consume(new Consumer()); + + public IEnumerable<MembershipEntry> AmbiguateMembershipsSwitchPatternMatching() { + foreach (var entry in entries) { + 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 + }; + yield return newState == entry.State ? entry : entry with { State = newState }; + } + } + + [Benchmark] + public void TestAmbiguateMembershipsSwitch() => AmbiguateMembershipsSwitch().Consume(new Consumer()); + + public IEnumerable<MembershipEntry> AmbiguateMembershipsSwitch() { + foreach (var entry in entries) { + if (!DoDisambiguate) { + yield return entry; + continue; + } + + MembershipTransition newState; + switch (entry.State) { + case MembershipTransition.ProfileUpdate: + newState = !DisambiguateProfileUpdates ? MembershipTransition.Join : entry.State; + break; + case MembershipTransition.Kick: + newState = !DisambiguateKicks ? MembershipTransition.Leave : entry.State; + break; + case MembershipTransition.Unban when !DisambiguateUnbans: + newState = MembershipTransition.Leave; + break; + case MembershipTransition.InviteAccepted when !DisambiguateInviteActions || !DisambiguateInviteAccepted: + newState = MembershipTransition.Join; + break; + case MembershipTransition.InviteRejected when !DisambiguateInviteActions || !DisambiguateInviteRejected: + + newState = MembershipTransition.Leave; + break; + case MembershipTransition.InviteRetracted when !DisambiguateInviteActions || !DisambiguateInviteRetracted: + newState = MembershipTransition.Leave; + break; + case MembershipTransition.KnockAccepted when !DisambiguateKnockActions || !DisambiguateKnockAccepted: + newState = MembershipTransition.Invite; + break; + case MembershipTransition.KnockRejected when !DisambiguateKnockActions || !DisambiguateKnockRejected: + newState = MembershipTransition.Leave; + break; + case MembershipTransition.KnockRetracted when !DisambiguateKnockActions || !DisambiguateKnockRetracted: + newState = MembershipTransition.Leave; + break; + default: + newState = entry.State; + break; + } + + yield return newState == entry.State ? entry : entry with { State = newState }; + } + } + + [Benchmark] + public void TestAmbiguateMembershipsIf() => AmbiguateMembershipsIf().Consume(new Consumer()); + + public IEnumerable<MembershipEntry> AmbiguateMembershipsIf() { + foreach (var entry in entries) { + MembershipTransition newState; + if (entry.State == MembershipTransition.ProfileUpdate && (!DoDisambiguate || !DisambiguateProfileUpdates)) + newState = MembershipTransition.Join; + else if ((entry.State == MembershipTransition.Kick && (!DoDisambiguate || !DisambiguateKicks)) || + (entry.State == MembershipTransition.Unban && (!DoDisambiguate || !DisambiguateUnbans))) + newState = MembershipTransition.Leave; + else if (entry.State == MembershipTransition.InviteAccepted && (!DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteAccepted)) + newState = MembershipTransition.Join; + else if ((entry.State == MembershipTransition.InviteRejected && (!DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteRejected)) || + (entry.State == MembershipTransition.InviteRetracted && (!DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteRetracted))) + newState = MembershipTransition.Leave; + else if (entry.State == MembershipTransition.KnockAccepted && (!DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockAccepted)) + newState = MembershipTransition.Invite; + else if ((entry.State == MembershipTransition.KnockRejected && (!DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockRejected)) || + (entry.State == MembershipTransition.KnockRetracted && (!DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockRetracted))) + newState = MembershipTransition.Leave; + else + newState = entry.State; + + yield return newState == entry.State ? entry : entry with { State = newState }; + } + } + + [Benchmark] + public void TestAmbiguateMembershipsStaticMap() => AmbiguateMembershipsStaticMap().Consume(new Consumer()); + + public IEnumerable<MembershipEntry> AmbiguateMembershipsStaticMap() { + Dictionary<MembershipTransition, MembershipTransition> _map = []; + if (!DoDisambiguate || !DisambiguateProfileUpdates) _map[MembershipTransition.ProfileUpdate] = MembershipTransition.Join; + if (!DoDisambiguate || !DisambiguateKicks) _map[MembershipTransition.Kick] = MembershipTransition.Leave; + if (!DoDisambiguate || !DisambiguateUnbans) _map[MembershipTransition.Unban] = MembershipTransition.Leave; + if (!DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteAccepted) _map[MembershipTransition.InviteAccepted] = MembershipTransition.Join; + if (!DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteRejected) _map[MembershipTransition.InviteRejected] = MembershipTransition.Leave; + if (!DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteRetracted) _map[MembershipTransition.InviteRetracted] = MembershipTransition.Leave; + if (!DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockAccepted) _map[MembershipTransition.KnockAccepted] = MembershipTransition.Invite; + if (!DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockRejected) _map[MembershipTransition.KnockRejected] = MembershipTransition.Leave; + if (!DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockRetracted) _map[MembershipTransition.KnockRetracted] = MembershipTransition.Leave; + FrozenDictionary<MembershipTransition, MembershipTransition> map = _map.ToFrozenDictionary(); + _map = null!; + foreach (var entry in entries) { + var newState = map.TryGetValue(entry.State, out var value) ? value : entry.State; + yield return newState == entry.State ? entry : entry with { State = newState }; + } + } + + [Benchmark] + public void TestAmbiguateMembershipsBinMask() => AmbiguateMembershipsBinMask().Consume(new Consumer()); + + public IEnumerable<MembershipEntry> AmbiguateMembershipsBinMask() { + uint mask = 0; + // dont mask last 4 bits + if (!DoDisambiguate || !DisambiguateProfileUpdates) mask |= (uint)MembershipTransition.ProfileUpdate >> 4; + if (!DoDisambiguate || !DisambiguateKicks) mask |= (uint)MembershipTransition.Kick >> 4; + if (!DoDisambiguate || !DisambiguateUnbans) mask |= (uint)MembershipTransition.Unban >> 4; + if (!DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteAccepted) mask |= (uint)MembershipTransition.InviteAccepted >> 4; + if (!DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteRejected) mask |= (uint)MembershipTransition.InviteRejected >> 4; + if (!DoDisambiguate || !DisambiguateInviteActions || !DisambiguateInviteRetracted) mask |= (uint)MembershipTransition.InviteRetracted >> 4; + if (!DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockAccepted) mask |= (uint)MembershipTransition.KnockAccepted >> 4; + if (!DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockRejected) mask |= (uint)MembershipTransition.KnockRejected >> 4; + if (!DoDisambiguate || !DisambiguateKnockActions || !DisambiguateKnockRetracted) mask |= (uint)MembershipTransition.KnockRetracted >> 4; + mask = (mask << 4) + 0b1111; + // Console.WriteLine(mask.ToString("b24")); + foreach (var entry in entries) { + if (((uint)entry.State & 0b1111_1111_0000) == 0) { + yield return entry; + continue; + } + + var newState = (MembershipTransition)((uint)entry.State & mask); + // Console.WriteLine(((uint)newState).ToString("b32")); + yield return newState == entry.State ? entry : entry with { State = newState }; + } + } +} \ No newline at end of file diff --git a/LibMatrix b/LibMatrix -Subproject 9ca482c6d179e5a7e31ce7d735ece5881d84724 +Subproject ca3e6878422b7b55ae52b43f49f89a19546ea51 diff --git a/MatrixUtils.Web/Classes/Constants/RoomConstants.cs b/MatrixUtils.Web/Classes/Constants/RoomConstants.cs
index 5df0d01..dc81d04 100644 --- a/MatrixUtils.Web/Classes/Constants/RoomConstants.cs +++ b/MatrixUtils.Web/Classes/Constants/RoomConstants.cs
@@ -1,6 +1,7 @@ namespace MatrixUtils.Web.Classes.Constants; public class RoomConstants { - public static readonly string[] DangerousRoomVersions = { "1", "8" }; - public const string RecommendedRoomVersion = "10"; + public static readonly string[] DangerousRoomVersions = ["1", "8"]; + public static readonly string[] UnsupportedRoomVersions = ["1", "2", "3", "4", "5", "6"]; + public const string RecommendedRoomVersion = "11"; } diff --git a/MatrixUtils.Web/Classes/RMUStorageWrapper.cs b/MatrixUtils.Web/Classes/RMUStorageWrapper.cs
index 337c7e4..e63c28e 100644 --- a/MatrixUtils.Web/Classes/RMUStorageWrapper.cs +++ b/MatrixUtils.Web/Classes/RMUStorageWrapper.cs
@@ -25,6 +25,10 @@ public class RMUStorageWrapper(ILogger<RMUStorageWrapper> logger, TieredStorageS await SetCurrentToken(currentToken = allTokens[0]); } + if (currentToken is null) { + await SetCurrentToken(currentToken = allTokens[0]); + } + if (!allTokens.Any(x => x.AccessToken == currentToken.AccessToken)) { await SetCurrentToken(currentToken = allTokens[0]); } diff --git a/MatrixUtils.Web/Pages/Rooms/PolicyList.razor b/MatrixUtils.Web/Pages/Rooms/PolicyList.razor
index 34d5880..94113dd 100644 --- a/MatrixUtils.Web/Pages/Rooms/PolicyList.razor +++ b/MatrixUtils.Web/Pages/Rooms/PolicyList.razor
@@ -370,7 +370,7 @@ else { #region Nasty, nasty internals, please ignore! private static class NastyInternalsPleaseIgnore { - public async static Task ExecuteKickWithWasmWorkers(WebWorkerService workerService, AuthenticatedHomeserverGeneric hs, StateEventResponse evt, List<string> roomIds) { + public static async Task ExecuteKickWithWasmWorkers(WebWorkerService workerService, AuthenticatedHomeserverGeneric hs, StateEventResponse evt, List<string> roomIds) { try { // var tasks = roomIds.Select(roomId => workerService.TaskPool.Invoke(ExecuteKickInternal, hs.WellKnownUris.Client, hs.AccessToken, roomId, content.Entity)).ToList(); var tasks = roomIds.Select(roomId => workerService.TaskPool.Invoke(ExecuteKickInternal2, hs.WellKnownUris, hs.AccessToken, roomId, evt)).ToList(); @@ -382,7 +382,7 @@ else { } } - private async static Task ExecuteKickInternal(string homeserverBaseUrl, string accessToken, string roomId, string entity) { + private static async Task ExecuteKickInternal(string homeserverBaseUrl, string accessToken, string roomId, string entity) { try { Console.WriteLine("args: " + string.Join(", ", homeserverBaseUrl, accessToken, roomId, entity)); Console.WriteLine($"Checking {roomId}..."); diff --git a/MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor b/MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor
index 90b652a..296852a 100644 --- a/MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor +++ b/MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor
@@ -1,45 +1,73 @@ -@page "/Tools/KnownHomeserverList" +@page "/Tools/Info/KnownHomeserverList" @using ArcaneLibs.Extensions +@using LibMatrix.RoomTypes +@using SpawnDev.BlazorJS.WebWorkers +@inject WebWorkerService workerService <h3>Known Homeserver List</h3> <hr/> @if (!IsFinished) { <p> - <b>Loading...</b> + <b>Loading... @RoomCount rooms remaining to process...</b> </p> } -@foreach (var (homeserver, members) in counts.OrderByDescending(x => x.Value)) { - <p>@homeserver - @members</p> +@{ + var shownCounts = counts.OrderByDescending(x => x.Value).AsEnumerable(); + if (!IsFinished && counts.Count > 500) { + shownCounts = shownCounts.Where(x => x.Value > 5); + } +} +@foreach (var (homeserver, members) in shownCounts.ToList()) { + <p>@homeserver - @members users</p> } <hr/> @code { Dictionary<string, List<string>> homeservers { get; set; } = new(); + Dictionary<string, int> counts { get; set; } = new(); + // List<HomeserverInfo> Homeservers = new(); bool IsFinished { get; set; } + // HomeserverInfoQueryProgress QueryProgress { get; set; } = new(); AuthenticatedHomeserverGeneric? hs { get; set; } + int RoomCount { get; set; } = 0; protected override async Task OnInitializedAsync() { hs = await RmuStorage.GetCurrentSessionOrNavigate(); if (hs is null) return; - var fetchTasks = (await hs.GetJoinedRooms()).Select(x=>x.GetMembersByHomeserverAsync()).ToAsyncEnumerable(); + var ss = new SemaphoreSlim(32, 32); + var rooms = await hs.GetJoinedRooms(); + RoomCount = rooms.Count; + var fetchTasks = rooms.Select(roomId => workerService.TaskPool.Invoke(() => InternalGetMembersByHomeserver(hs.WellKnownUris.Client, hs.AccessToken, roomId.RoomId))).ToList().ToAsyncEnumerable(); + // var fetchTasks = rooms.Select(async x => { + // await ss.WaitAsync(); + // var res = await x.GetMembersByHomeserverAsync(); + // ss.Release(); + // return res; + // }).ToAsyncEnumerable(); await foreach (var result in fetchTasks) { foreach (var (resHomeserver, resMembers) in result) { if (!homeservers.TryAdd(resHomeserver, resMembers)) { homeservers[resHomeserver].AddRange(resMembers); } + counts[resHomeserver] = homeservers[resHomeserver].Count; } - // StateHasChanged(); + + RoomCount--; + StateHasChanged(); // await Task.Delay(250); + await Task.Yield(); } foreach (var resHomeserver in homeservers.Keys) { homeservers[resHomeserver] = homeservers[resHomeserver].Distinct().ToList(); counts[resHomeserver] = homeservers[resHomeserver].Count; + StateHasChanged(); + await Task.Yield(); } IsFinished = true; @@ -48,4 +76,10 @@ await base.OnInitializedAsync(); } + private static async Task<Dictionary<string, List<string>>> InternalGetMembersByHomeserver(string homeserverBaseUrl, string accessToken, string roomId) { + var hs = new AuthenticatedHomeserverGeneric(homeserverBaseUrl, new() { Client = homeserverBaseUrl }, null, accessToken); + var room = hs.GetRoom(roomId); + return await room.GetMembersByHomeserverAsync(); + } + } \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/InviteCounter.razor b/MatrixUtils.Web/Pages/Tools/InviteCounter.razor
index e2a0393..fa94f18 100644 --- a/MatrixUtils.Web/Pages/Tools/InviteCounter.razor +++ b/MatrixUtils.Web/Pages/Tools/InviteCounter.razor
@@ -1,6 +1,8 @@ @page "/Tools/InviteCounter" @using System.Collections.ObjectModel +@using ArcaneLibs.Extensions @using LibMatrix.EventTypes.Spec.State.RoomInfo +@using LibMatrix.Filters <h3>User Trace</h3> <hr/> @@ -13,7 +15,7 @@ <details> <summary>Results</summary> - @foreach (var (userId, events) in invites.OrderByDescending(x=>x.Value).ToList()) { + @foreach (var (userId, events) in invites.OrderByDescending(x => x.Value).ToList()) { <p>@userId: @events</p> } </details> @@ -27,16 +29,15 @@ private ObservableCollection<string> log { get; set; } = new(); private Dictionary<string, int> invites { get; set; } = new(); 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(); @@ -44,22 +45,21 @@ private async Task<string> Execute() { var room = hs.GetRoom(roomId); - var events = room.GetManyMessagesAsync(limit: int.MaxValue); + var filter = new SyncFilter.EventFilter(types: ["m.room.member"]); + var events = room.GetManyMessagesAsync(limit: int.MaxValue, filter: filter.ToJson(indent: false, ignoreNull: true)); await foreach (var resp in events) { var all = resp.State.Concat(resp.Chunk); foreach (var evt in all) { - if(evt.Type != RoomMemberEventContent.EventId) continue; + if (evt.Type != RoomMemberEventContent.EventId) continue; var content = evt.TypedContent as RoomMemberEventContent; - if(content.Membership != "invite") continue; - if(!invites.ContainsKey(evt.Sender)) invites[evt.Sender] = 0; + if (content.Membership != "invite") continue; + if (!invites.ContainsKey(evt.Sender)) invites[evt.Sender] = 0; invites[evt.Sender]++; } log.Add($"{resp.State.Count} state, {resp.Chunk.Count} timeline"); } - - - + StateHasChanged(); return ""; diff --git a/MatrixUtils.Web/Properties/launchSettings.json b/MatrixUtils.Web/Properties/launchSettings.json
index aa41dc8..660211d 100644 --- a/MatrixUtils.Web/Properties/launchSettings.json +++ b/MatrixUtils.Web/Properties/launchSettings.json
@@ -13,7 +13,7 @@ "dotnetRunMessages": true, "launchBrowser": false, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "http://localhost:5117", + "applicationUrl": "http://*:5117", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/MatrixUtils.Web/Shared/MainLayout.razor b/MatrixUtils.Web/Shared/MainLayout.razor
index f32c19e..0392d9a 100644 --- a/MatrixUtils.Web/Shared/MainLayout.razor +++ b/MatrixUtils.Web/Shared/MainLayout.razor
@@ -9,7 +9,7 @@ <div class="top-row px-4"> @* <PortableDevTools/> *@ @* <ResourceUsage/> *@ - <a style="color: #ccc; text-decoration: underline" href="https://cgit.rory.gay/matrix/MatrixRoomUtils.git/" target="_blank">Git</a> + <a style="color: #ccc; text-decoration: underline" href="https://cgit.rory.gay/matrix/tools/MatrixUtils.git/" target="_blank">Git</a> <a style="color: #ccc; text-decoration: underline" href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support" target="_blank">Matrix</a> </div>