@page "/Tools/UserTrace"
@using ArcaneLibs.Extensions
@using LibMatrix.RoomTypes
@using System.Collections.ObjectModel
@using LibMatrix
@using System.Collections.Frozen
@using LibMatrix.EventTypes.Spec.State
@using MatrixUtils.Abstractions
User Trace
Users:
Import from room (ID)
Rooms to be searched (@rooms.Count)
@foreach (var room in rooms) {
@room.Room.RoomId
}
Execute
Results
@foreach (var (userId, events) in matches) {
@userId
@foreach (var match in events) {
-
- @match.RoomName (@match.Room.RoomId)
- Membership: @(match.Event.RawContent.ToJson(indent: false))
}
}
@foreach (var line in log.Reverse()) {
@line
}
@code {
private ObservableCollection log { get; set; } = new();
List rooms { get; set; } = new();
Dictionary> matches = new();
private string UserIdString {
get => string.Join("\n", UserIDs);
set => UserIDs = value.Split("\n").Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
}
private List UserIDs { get; set; } = new();
protected override async Task OnInitializedAsync() {
log.CollectionChanged += (sender, args) => StateHasChanged();
var hs = await RMUStorage.GetCurrentSessionOrNavigate();
if (hs is null) return;
var sessions = await RMUStorage.GetAllTokens();
var baseRooms = new List();
foreach (var userAuth in sessions) {
var session = await RMUStorage.GetSession(userAuth);
if (session is not null) {
baseRooms.AddRange(await session.GetJoinedRooms());
var sessionRooms = (await session.GetJoinedRooms()).Where(x => !rooms.Any(y => y.Room.RoomId == x.RoomId)).ToList();
StateHasChanged();
log.Add($"Got {sessionRooms.Count} rooms for {userAuth.UserId}");
}
}
log.Add("Done fetching rooms!");
baseRooms = baseRooms.DistinctBy(x => x.RoomId).ToList();
// rooms.CollectionChanged += (sender, args) => StateHasChanged();
var tasks = baseRooms.Select(async newRoom => {
bool success = false;
while (!success)
try {
var state = await newRoom.GetFullStateAsListAsync();
var newRoomInfo = new RoomInfo(newRoom, state);
rooms.Add(newRoomInfo);
log.Add($"Got {newRoomInfo.StateEvents.Count} events for {newRoomInfo.RoomName}");
success = true;
}
catch (MatrixException e) {
log.Add($"Failed to fetch room {newRoom.RoomId}! {e}");
throw;
}
catch (HttpRequestException e) {
log.Add($"Failed to fetch room {newRoom.RoomId}! {e}");
}
});
await Task.WhenAll(tasks);
log.Add($"Done fetching members!");
UserIDs.RemoveAll(x => sessions.Any(y => y.UserId == x));
StateHasChanged();
Console.WriteLine("Rerendered!");
await base.OnInitializedAsync();
}
private async Task Execute() {
foreach (var userId in UserIDs) {
matches.Add(userId, new List());
foreach (var room in rooms) {
var state = room.StateEvents.Where(x => x!.Type == RoomMemberEventContent.EventId).ToList();
if (state!.Any(x => x.StateKey == userId)) {
matches[userId].Add(new() {
Event = state.First(x => x.StateKey == userId),
Room = room.Room,
RoomName = room.RoomName ?? "No name"
});
}
}
}
StateHasChanged();
return "";
}
public string? ImportFromRoomId { get; set; }
private async Task DoImportFromRoomId() {
try {
if (ImportFromRoomId is null) return;
var room = rooms.FirstOrDefault(x => x.Room.RoomId == ImportFromRoomId);
UserIdString = string.Join("\n", (await room.Room.GetMembersListAsync()).Select(x => x.StateKey));
}
catch (Exception e) {
Console.WriteLine(e);
log.Add("Could not fetch members list!\n" + e.ToString());
}
StateHasChanged();
}
private class Match {
public GenericRoom Room;
public StateEventResponse Event;
public string RoomName { get; set; }
}
}