@page "/Tools/Moderation/UserTrace"
@using ArcaneLibs.Extensions
@using LibMatrix.RoomTypes
@using System.Collections.ObjectModel
@using LibMatrix
User Trace
Users:
Import from room (ID)
Rooms to be searched (@rooms.Count)
@foreach (var room in rooms) {
@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();
List rooms { get; set; } = [];
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));
foreach (var session in await RMUStorage.GetAllTokens()) {
var _hs = await RMUStorage.GetSession(session);
if (_hs is not null) {
rooms.AddRange(await _hs.GetJoinedRooms());
log.Add($"Got {rooms.Count} rooms after adding {_hs.UserId}");
}
}
//get distinct rooms evenly distributed per session, accounting for count per session
rooms = rooms.OrderBy(x => rooms.Count(y => y.Homeserver == x.Homeserver)).DistinctBy(x => x.RoomId).ToList();
log.Add($"Got {rooms.Count} rooms");
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"
// });
// }
// }
log.Add($"Searching for {userId}...");
await foreach (var match in GetMatches(userId)) {
matches[userId].Add(match);
}
}
log.Add("Done!");
StateHasChanged();
return "";
}
public string? ImportFromRoomId { get; set; }
private async Task DoImportFromRoomId() {
try {
if (ImportFromRoomId is null) return;
var room = rooms.FirstOrDefault(x => x.RoomId == ImportFromRoomId);
UserIdString = string.Join("\n", (await 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; }
}
private async IAsyncEnumerable GetMatches(string userId) {
var results = rooms.Select(async room => {
var state = await room.GetStateEventOrNullAsync(room.RoomId, userId);
if (state is not null) {
return new Match {
Room = room,
Event = state,
RoomName = await room.GetNameOrFallbackAsync()
};
}
return null;
}).ToAsyncEnumerable();
await foreach (var result in results) {
if (result is not null) {
yield return result;
}
}
}
}