@page "/Moderation/UserRoomHistory/{UserId}" @using LibMatrix.EventTypes.Spec.State @using LibMatrix.RoomTypes @using ArcaneLibs.Extensions @using MatrixUtils.Abstractions

UserRoomHistory

Enter mxid: @if (string.IsNullOrWhiteSpace(UserId)) {

UserId is null!

} else {

Checked @checkedRooms.Count so far...

@if (currentHs is not null) {

Checking rooms from @currentHs.UserId's perspective

} else if (checkedRooms.Count > 1) {

Done!

} @foreach (var (state, rooms) in matchingStates) { @state
@foreach (var roomInfo in rooms) { } } } @code { private string? _userId; [Parameter] public string? UserId { get => _userId; set { _userId = value; FindMember(value); } } private List hss = new(); private AuthenticatedHomeserverGeneric? currentHs { get; set; } protected override async Task OnInitializedAsync() { var hs = await RMUStorage.GetCurrentSessionOrNavigate(); if (hs is null) return; var sessions = await RMUStorage.GetAllTokens(); foreach (var userAuth in sessions) { var session = await RMUStorage.GetSession(userAuth); if (session is not null) { hss.Add(session); StateHasChanged(); } } StateHasChanged(); Console.WriteLine("Rerendered!"); await base.OnInitializedAsync(); if (!string.IsNullOrWhiteSpace(UserId)) FindMember(UserId); } public Dictionary> matchingStates = new(); public List checkedRooms = new(); private SemaphoreSlim _semaphoreSlim = new(1, 1); public async Task FindMember(string mxid) { await _semaphoreSlim.WaitAsync(); if (mxid != UserId) { _semaphoreSlim.Release(); return; //abort if changed } matchingStates.Clear(); foreach (var homeserver in hss) { currentHs = homeserver; var rooms = await homeserver.GetJoinedRooms(); rooms.RemoveAll(x => checkedRooms.Contains(x.RoomId)); checkedRooms.AddRange(rooms.Select(x => x.RoomId)); var tasks = rooms.Select(x => GetMembershipAsync(x, mxid)).ToAsyncEnumerable(); await foreach (var (room, state) in tasks) { if (state is null) continue; if (!matchingStates.ContainsKey(state.Membership)) matchingStates.Add(state.Membership, new()); var roomInfo = new RoomInfo(room); matchingStates[state.Membership].Add(roomInfo); roomInfo.StateEvents.Add(new() { Type = RoomNameEventContent.EventId, TypedContent = new RoomNameEventContent() { Name = await room.GetNameOrFallbackAsync(4) }, RoomId = null, Sender = null, EventId = null //TODO implement }); StateHasChanged(); if (mxid != UserId) { _semaphoreSlim.Release(); return; //abort if changed } } StateHasChanged(); } currentHs = null; StateHasChanged(); _semaphoreSlim.Release(); } public async Task<(GenericRoom roomId, RoomMemberEventContent? content)> GetMembershipAsync(GenericRoom room, string mxid) { return (room, await room.GetStateOrNullAsync(RoomMemberEventContent.EventId, mxid)); } }