diff options
Diffstat (limited to 'MatrixRoomUtils.Web/Pages/Tools/KnownHomeserverList.razor')
-rw-r--r-- | MatrixRoomUtils.Web/Pages/Tools/KnownHomeserverList.razor | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/MatrixRoomUtils.Web/Pages/Tools/KnownHomeserverList.razor b/MatrixRoomUtils.Web/Pages/Tools/KnownHomeserverList.razor new file mode 100644 index 0000000..939838e --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/Tools/KnownHomeserverList.razor @@ -0,0 +1,171 @@ +@page "/KnownHomeserverList" +@using System.Diagnostics +@using ArcaneLibs.Extensions +@using LibMatrix.Homeservers +@using LibMatrix.RoomTypes +<h3>Known Homeserver List</h3> +<hr/> + +@if (!IsFinished) { + <p>Loading... Please wait...</p> + <progress value="@QueryProgress.ProcessedRooms" max="@QueryProgress.TotalRooms"></progress> + <p>@QueryProgress.ProcessedRooms / @QueryProgress.TotalRooms</p> + @foreach (var (room, state) in QueryProgress.ProcessedUsers.Where(x => !x.Value.IsFinished).OrderByDescending(x => x.Value.Total).ToList()) { + @if (state.Blocked) { + <p>🔒 @room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...</p> + } + else if (state.Slowmode) { + <p>🐢 @room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...</p> + } + else { + <p>@room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...</p> + } + <progress value="@state.Processed" max="@state.Total"></progress> + } +} +else { + @foreach (var server in HomeServers.OrderByDescending(x => x.KnownUserCount).ThenBy(x => x.Server).ToList()) { + <p>@server.Server - @server.KnownUserCount</p> + } +} +<hr/> + +@code { + List<HomeServerInfo> HomeServers = new(); + bool IsFinished { get; set; } + HomeServerInfoQueryProgress QueryProgress { get; set; } = new(); + AuthenticatedHomeserverGeneric hs { get; set; } + protected override async Task OnInitializedAsync() { + hs = await MRUStorage.GetCurrentSessionOrNavigate(); + if (hs is null) return; + var sw = Stopwatch.StartNew(); + HomeServers = await GetHomeservers(progressCallback: async progress => { + if (sw.ElapsedMilliseconds > 1000) { + Console.WriteLine("Progress updated..."); + QueryProgress = progress; + StateHasChanged(); + Console.WriteLine("Progress rendered!"); + sw.Restart(); + await Task.Delay(100); + return true; + } + Console.WriteLine($"Progress updated, but not rendering because only {sw.ElapsedMilliseconds}ms elapsed since last call..."); + return false; + }); + + IsFinished = true; + StateHasChanged(); + Console.WriteLine("Rerendered!"); + await base.OnInitializedAsync(); + } + + private async Task<List<HomeServerInfo>> GetHomeservers(int memberLimit = 1000, Func<HomeServerInfoQueryProgress, Task<bool>>? progressCallback = null) { + HomeServerInfoQueryProgress progress = new(); + List<HomeServerInfo> homeServers = new(); + + var rooms = await hs.GetJoinedRooms(); + progress.TotalRooms = rooms.Count; + + var semaphore = new SemaphoreSlim(4); + var semLock = new SemaphoreSlim(1); + var tasks = rooms.Select(async room => { + await semaphore.WaitAsync(); + progress.ProcessedUsers.Add(room, new HomeServerInfoQueryProgress.State()); + Console.WriteLine($"Fetching states for room ({rooms.IndexOf(room)}/{rooms.Count}) ({room.RoomId})"); + var states = room.GetFullStateAsync(); + await foreach (var state in states) { + if (state.Type is not "m.room.member") continue; + progress.ProcessedUsers[room].Total++; + + if (homeServers.Any(x => x.Server == state.StateKey.Split(':')[1])) continue; + homeServers.Add(new HomeServerInfo { Server = state.StateKey.Split(':')[1] }); + Console.WriteLine($"Added new homeserver {state.StateKey.Split(':')[1]}"); + } + semaphore.Release(); + progress.ProcessedUsers[room].IsFinished = true; + progress.ProcessedRooms++; + if (progressCallback is not null) + await progressCallback.Invoke(progress); + + + + // states.RemoveAll(x => x.Type != "m.room.member" || (x.TypedContent as RoomMemberEventContent).Membership != "join"); + // Console.WriteLine($"Room {room.RoomId} has {states.Count} members"); + // if (states.Count > memberLimit) { + // Console.WriteLine("Skipping!"); + // semaphore.Release(); + // progress.ProcessedUsers.Remove(room); + // progress.TotalRooms--; + // return; + // } + // progress.ProcessedUsers[room].Total = states.Count; + // var updateInterval = progress.ProcessedUsers[room].Total >= 1000 ? 1000 : 100; + // while (progress.ProcessedUsers.Any(x => x.Value.Total == 0) && progress.ProcessedUsers[room].Total >= 1000) { + // progress.ProcessedUsers[room].Blocked = true; + // await Task.Delay(1000); + // // if(progressCallback is not null) + // // await progressCallback.Invoke(progress); + // } + // progress.ProcessedUsers[room].Blocked = false; + // var processedStates = 0; + // foreach (var state in states) { + // await semLock.WaitAsync(); + // semLock.Release(); + // if (progress.ProcessedUsers.Count(x => x.Value.Total == 0) > 5 && progress.ProcessedUsers[room].Total >= 200) { + // progress.ProcessedUsers[room].Slowmode = true; + // await Task.Delay(progress.ProcessedUsers[room].Total >= 500 ? 1000 : 100); + // } + // else { + // progress.ProcessedUsers[room].Slowmode = false; + // } + // if (!homeServers.Any(x => x.Server == state.StateKey.Split(':')[1])) { + // homeServers.Add(new HomeServerInfo { Server = state.StateKey.Split(':')[1] }); + // } + // var hs = homeServers.First(x => x.Server == state.StateKey.Split(':')[1]); + // if (!hs.KnownUsers.Contains(state.StateKey.Split(':')[0])) + // hs.KnownUsers.Add(state.StateKey.Split(':')[0]); + // if (++progress.ProcessedUsers[room].Processed % updateInterval == 0 && progressCallback is not null) { + // await semLock.WaitAsync(); + // var _ = await progressCallback.Invoke(progress); + // semLock.Release(); + // } + // } + // Console.WriteLine("Collected states!"); + // progress.ProcessedRooms++; + // progress.ProcessedUsers[room].IsFinished = true; + // progressCallback?.Invoke(progress); + // semaphore.Release(); + }); + await Task.WhenAll(tasks); + + Console.WriteLine("Calculating member counts..."); + homeServers.ForEach(x => x.KnownUserCount = x.KnownUsers.Count); + Console.WriteLine(homeServers.First(x => x.Server == "rory.gay").ToJson()); + Console.WriteLine("Recalculated!"); + return homeServers; + } + + class HomeServerInfo { + public string Server { get; set; } + public int? KnownUserCount { get; set; } + public List<string> KnownUsers { get; } = new(); + } + + class HomeServerInfoQueryProgress { + public int ProcessedRooms { get; set; } + public int TotalRooms { get; set; } + public Dictionary<GenericRoom, State> ProcessedUsers { get; } = new(); + public List<HomeServerInfo> CurrentState { get; set; } = new(); + + public class State { + public int Processed { get; set; } + public int Total { get; set; } + public bool Blocked { get; set; } + public bool Slowmode { get; set; } + public float Progress => (float)Processed / Total; + public bool IsFinished { get; set; } + public Stopwatch Timing { get; } = Stopwatch.StartNew(); + } + } + +} |