about summary refs log tree commit diff
path: root/MatrixUtils.Web/Pages/Tools
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixUtils.Web/Pages/Tools')
-rw-r--r--MatrixUtils.Web/Pages/Tools/Debug/LeaveRoom.razor (renamed from MatrixUtils.Web/Pages/Tools/LeaveRoom.razor)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/Debug/MediaLocator.razor (renamed from MatrixUtils.Web/Pages/Tools/MediaLocator.razor)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/Debug/MigrateRoom.razor (renamed from MatrixUtils.Web/Pages/Tools/MigrateRoom.razor)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/Debug/SpaceDebug.razor (renamed from MatrixUtils.Web/Pages/Tools/SpaceDebug.razor)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/Index.razor39
-rw-r--r--MatrixUtils.Web/Pages/Tools/Index.razor.css6
-rw-r--r--MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor (renamed from MatrixUtils.Web/Pages/Tools/KnownHomeserverList.razor)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor (renamed from MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor.css (renamed from MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor.css)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor (renamed from MatrixUtils.Web/Pages/Tools/SessionCount.razor)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/DraupnirProtectedRoomsEditor.razor102
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor (renamed from MatrixUtils.Web/Pages/Tools/InviteCounter.razor)9
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/MassCMEBan.razor (renamed from MatrixUtils.Web/Pages/Tools/MassCMEBan.razor)8
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor276
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor (renamed from MatrixUtils.Web/Pages/Tools/RoomIntersections.razor)2
-rw-r--r--MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor (renamed from MatrixUtils.Web/Pages/Tools/UserTrace.razor)6
-rw-r--r--MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor (renamed from MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor (renamed from MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor)0
-rw-r--r--MatrixUtils.Web/Pages/Tools/User/ViewAccountData.razor (renamed from MatrixUtils.Web/Pages/Tools/ViewAccountData.razor)0
19 files changed, 419 insertions, 29 deletions
diff --git a/MatrixUtils.Web/Pages/Tools/LeaveRoom.razor b/MatrixUtils.Web/Pages/Tools/Debug/LeaveRoom.razor

index 841552e..841552e 100644 --- a/MatrixUtils.Web/Pages/Tools/LeaveRoom.razor +++ b/MatrixUtils.Web/Pages/Tools/Debug/LeaveRoom.razor
diff --git a/MatrixUtils.Web/Pages/Tools/MediaLocator.razor b/MatrixUtils.Web/Pages/Tools/Debug/MediaLocator.razor
index 6e87926..6e87926 100644 --- a/MatrixUtils.Web/Pages/Tools/MediaLocator.razor +++ b/MatrixUtils.Web/Pages/Tools/Debug/MediaLocator.razor
diff --git a/MatrixUtils.Web/Pages/Tools/MigrateRoom.razor b/MatrixUtils.Web/Pages/Tools/Debug/MigrateRoom.razor
index 11d35f1..11d35f1 100644 --- a/MatrixUtils.Web/Pages/Tools/MigrateRoom.razor +++ b/MatrixUtils.Web/Pages/Tools/Debug/MigrateRoom.razor
diff --git a/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor b/MatrixUtils.Web/Pages/Tools/Debug/SpaceDebug.razor
index 263879b..263879b 100644 --- a/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor +++ b/MatrixUtils.Web/Pages/Tools/Debug/SpaceDebug.razor
diff --git a/MatrixUtils.Web/Pages/Tools/Index.razor b/MatrixUtils.Web/Pages/Tools/Index.razor
index f1e04a3..3aec2e3 100644 --- a/MatrixUtils.Web/Pages/Tools/Index.razor +++ b/MatrixUtils.Web/Pages/Tools/Index.razor
@@ -1,10 +1,31 @@ @page "/Tools" -<h3>Other tools</h3> - -<a href="/Tools/CopyPowerlevel">Copy highest powerlevel across all session</a><br/> -<a href="/Tools/KnownHomeserverList">Find all homeservers you share a room with</a><br/> -<a href="/Tools/MassRoomJoin">Join room across all session</a><br/> -<a href="/Tools/MediaLocator">Locate lost media</a><br/> -<a href="/Tools/SpaceDebug">Debug space relationships</a><br/> -<a href="/Tools/MigrateRoom">Migrate users from a split room to a new room</a><br/> -<a href="/Tools/LeaveRoom">Leave room by ID</a><br/> +<h3>Index of /Tools</h3> + +<h4 class="tool-category">Information tools</h4> +<hr/> +<a href="/Tools/Info/PolicyListActivity">View policy list activity</a><br/> +<a href="/Tools/Info/KnownHomeserverList">Find all homeservers you share a room with</a><br/> +<a href="/Tools/Info/SessionCount">Show session counts for users in a given room</a><br/> + +<h4 class="tool-category">User tools</h4> +<hr/> +<a href="/Tools/User/MassRoomJoin">Join room across all session</a><br/> +<a href="/Tools/User/CopyPowerlevel">Copy highest powerlevel across all session</a><br/> +<a href="/Tools/User/ViewAccountData">View account data</a><br/> + +<h4 class="tool-category">Moderation tools</h4> +<hr/> +<a href="/Tools/Moderation/InviteCounter">Count invites by inviter</a><br/> +<a href="/Tools/Moderation/MembershipHistory">View membership history</a><br/> +<a href="/Tools/Moderation/UserTrace">Trace user across rooms</a><br/> +<a href="/tools/Moderation/MassCMEBan">Mass write policies to Community Moderation Effort</a><br/> +<a href="/tools/Moderation/RoomIntersections">Find rooms with common users</a><br/> +<a href="/tools/Moderation/DraupnirProtectedRoomsEditor">Edit Draupnir protected rooms set</a><br/> + + +<h4 class="tool-category">Debugging tools</h4> +<hr/> +<a href="/Tools/Debug/SpaceDebug">Debug space relationships</a><br/> +<a href="/Tools/Debug/LeaveRoom">Leave room by ID</a><br/> +<a href="/Tools/Debug/MediaLocator">Locate lost media</a><br/> +<a href="/Tools/Debug/MigrateRoom">Migrate users from a split room to a new room</a><br/> diff --git a/MatrixUtils.Web/Pages/Tools/Index.razor.css b/MatrixUtils.Web/Pages/Tools/Index.razor.css new file mode 100644
index 0000000..c9bd995 --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/Index.razor.css
@@ -0,0 +1,6 @@ +.tool-category { + margin-top: 20px; +} +hr{ + margin: unset; +} \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/KnownHomeserverList.razor b/MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor
index ddd7b15..ddd7b15 100644 --- a/MatrixUtils.Web/Pages/Tools/KnownHomeserverList.razor +++ b/MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor
diff --git a/MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor b/MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor
index c94d0b0..c94d0b0 100644 --- a/MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor +++ b/MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor
diff --git a/MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor.css b/MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor.css
index 443fdb5..443fdb5 100644 --- a/MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor.css +++ b/MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor.css
diff --git a/MatrixUtils.Web/Pages/Tools/SessionCount.razor b/MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor
index 3b68bfa..3b68bfa 100644 --- a/MatrixUtils.Web/Pages/Tools/SessionCount.razor +++ b/MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor
diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/DraupnirProtectedRoomsEditor.razor b/MatrixUtils.Web/Pages/Tools/Moderation/DraupnirProtectedRoomsEditor.razor new file mode 100644
index 0000000..805bd40 --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/Moderation/DraupnirProtectedRoomsEditor.razor
@@ -0,0 +1,102 @@ +@page "/Moderation/DraupnirProtectedRoomsEditor" +@page "/Tools/Moderation/DraupnirProtectedRoomsEditor" +@using System.Text.Json.Serialization +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.RoomTypes +<h3>Edit Draupnir protected rooms</h3> +<hr/> +<p><b>Note:</b> You will need to restart Draupnir after applying changes!</p> +<p>Minor note: This <i>should</i> also work with Mjolnir, but this hasn't been tested, and as such functionality cannot be guaranteed.</p> + +@if (data is not null) { + <div class="row"> + <div class="col-12"> + <h4>Current rooms</h4> + <ul> + @foreach (var room in data.Rooms) { + <li>@room</li> + } + </ul> + <hr/> + <h4>Tickyboxes</h4> + <table class="table"> + <thead> + <tr> + <th></th> @* Checkbox column *@ + <th>Kick?</th> @* PL > kick *@ + <th>Ban?</th> @* PL > ban *@ + <th>ACL?</th> @* PL > m.room.server_acls event *@ + <th>Room ID</th> + <th>Room name</th> + </tr> + </thead> + <tbody> + @foreach (var room in Rooms.OrderBy(x => x.RoomName)) { + <tr> + <td> + <input type="checkbox" @bind="room.IsProtected"/> + </td> + <td>@(room.PowerLevels.Kick <= room.PowerLevels.GetUserPowerLevel(hs.UserId) ? "X" : "")</td> + <td>@(room.PowerLevels.Ban <= room.PowerLevels.GetUserPowerLevel(hs.UserId) ? "X" : "")</td> + <td>@(room.PowerLevels.UserHasStatePermission(hs.UserId, RoomServerACLEventContent.EventId) ? "X" : "")</td> + <td>@room.Room.RoomId</td> + <td>@room.RoomName</td> + </tr> + } + </tbody> + </table> + </div> + </div> +} +<br/> +<LinkButton OnClick="@Apply">Apply</LinkButton> + + +@code { + private DraupnirProtectedRoomsData data { get; set; } = new(); + private List<EditorRoomInfo> Rooms { get; set; } = new(); + private AuthenticatedHomeserverGeneric hs { get; set; } + + protected override async Task OnInitializedAsync() { + hs = await RMUStorage.GetCurrentSessionOrNavigate(); + if (hs is null) return; + data = await hs.GetAccountDataAsync<DraupnirProtectedRoomsData>("org.matrix.mjolnir.protected_rooms"); + StateHasChanged(); + var tasks = (await hs.GetJoinedRooms()).Select(async room => { + var plTask = room.GetPowerLevelsAsync(); + var roomNameTask = room.GetNameOrFallbackAsync(); + var EditorRoomInfo = new EditorRoomInfo { + Room = room, + IsProtected = data.Rooms.Contains(room.RoomId), + RoomName = await roomNameTask, + PowerLevels = await plTask + }; + + Rooms.Add(EditorRoomInfo); + StateHasChanged(); + return Task.CompletedTask; + }).ToList(); + await Task.WhenAll(tasks); + await Task.Delay(500); + StateHasChanged(); + } + + private class DraupnirProtectedRoomsData { + [JsonPropertyName("rooms")] + public List<string> Rooms { get; set; } = new(); + } + + private class EditorRoomInfo { + public GenericRoom Room { get; set; } + public bool IsProtected { get; set; } + public string RoomName { get; set; } + public RoomPowerLevelEventContent PowerLevels { get; set; } + } + + private async Task Apply() { + Console.WriteLine(string.Join('\n', Rooms.Where(x => x.IsProtected).Select(x => x.Room.RoomId))); + data.Rooms = Rooms.Where(x => x.IsProtected).Select(x => x.Room.RoomId).ToList(); + await hs.SetAccountDataAsync("org.matrix.mjolnir.protected_rooms", data); + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/InviteCounter.razor b/MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor
index 8f4b4dd..2123d4d 100644 --- a/MatrixUtils.Web/Pages/Tools/InviteCounter.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor
@@ -1,12 +1,7 @@ -@page "/Tools/InviteCounter" -@using ArcaneLibs.Extensions -@using LibMatrix.RoomTypes +@page "/Tools/Moderation/InviteCounter" @using System.Collections.ObjectModel -@using LibMatrix -@using System.Collections.Frozen @using LibMatrix.EventTypes.Spec.State -@using MatrixUtils.Abstractions -<h3>User Trace</h3> +<h3>Invite counter</h3> <hr/> <br/> diff --git a/MatrixUtils.Web/Pages/Tools/MassCMEBan.razor b/MatrixUtils.Web/Pages/Tools/Moderation/MassCMEBan.razor
index cbbca9e..ea1e5f6 100644 --- a/MatrixUtils.Web/Pages/Tools/MassCMEBan.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/MassCMEBan.razor
@@ -1,12 +1,6 @@ -@page "/Tools/MassCMEBan" -@using ArcaneLibs.Extensions -@using LibMatrix.RoomTypes +@page "/Tools/Moderation/MassCMEBan" @using System.Collections.ObjectModel -@using LibMatrix -@using System.Collections.Frozen -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.Policy -@using MatrixUtils.Abstractions <h3>User Trace</h3> <hr/> diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor b/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor new file mode 100644
index 0000000..e5ba004 --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor
@@ -0,0 +1,276 @@ +@page "/Tools/Moderation/MembershipHistory" +@using System.Collections.ObjectModel +@using LibMatrix +@using LibMatrix.EventTypes.Spec.State +<h3>Membership history viewer</h3> +<hr/> + +<br/> +<span>Room ID: </span> +<InputText @bind-Value="@roomId"></InputText> +<LinkButton OnClick="@Execute">Execute</LinkButton> +<p><InputCheckbox @bind-Value="ChronologicalOrder"/> Chronological order</p> +<p> + <span>Show </span> + <InputCheckbox @bind-Value="ShowJoins"/> joins + <InputCheckbox @bind-Value="ShowLeaves"/> leaves + <InputCheckbox @bind-Value="ShowUpdates"/> profile updates + <InputCheckbox @bind-Value="ShowKnocks"/> knocks + <InputCheckbox @bind-Value="ShowInvites"/> invites + <InputCheckbox @bind-Value="ShowKicks"/> kicks + <InputCheckbox @bind-Value="ShowBans"/> bans +</p> +<p> + <LinkButton OnClick="@(async () => { ShowJoins = ShowLeaves = ShowUpdates = ShowKnocks = ShowInvites = ShowKicks = ShowBans = false; })">Hide all</LinkButton> + <LinkButton OnClick="@(async () => { ShowJoins = ShowLeaves = ShowUpdates = ShowKnocks = ShowInvites = ShowKicks = ShowBans = true; })">Show all</LinkButton> + <LinkButton OnClick="@(async () => { ShowJoins ^= true; ShowLeaves ^= true; ShowUpdates ^= true; ShowKnocks ^= true; ShowInvites ^= true; ShowKicks ^= true; ShowBans ^= true; })">Toggle all</LinkButton> +</p> +<p> + <span>Sender: </span> + <InputSelect @bind-Value="Sender"> + <option value="">All</option> + @foreach (var sender in Memberships.Select(x => x.Sender).Distinct()) { + <option value="@sender">@sender</option> + } + </InputSelect> +</p> +<p> + <span>User: </span> + <InputSelect @bind-Value="User"> + <option value="">All</option> + @foreach (var user in Memberships.Select(x => x.StateKey).Distinct()) { + <option value="@user">@user</option> + } + </InputSelect> +</p> + + +<br/> + +<details> + <summary>Results</summary> + @{ + Dictionary<string, StateEventResponse> previousMemberships = []; + var filteredMemberships = Memberships.AsEnumerable(); + if (ChronologicalOrder) { + filteredMemberships = filteredMemberships.Reverse(); + } + if(!string.IsNullOrWhiteSpace(Sender)) { + filteredMemberships = filteredMemberships.Where(x => x.Sender == Sender); + } + if(!string.IsNullOrWhiteSpace(User)) { + filteredMemberships = filteredMemberships.Where(x => x.StateKey == User); + } + + @foreach (var membership in filteredMemberships) { + RoomMemberEventContent content = membership.TypedContent as RoomMemberEventContent; + @switch (content.Membership) { + case RoomMemberEventContent.MembershipTypes.Invite: { + if (_showInvites) { + <p style="color: green;">@membership.Sender invited @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p> + } + + break; + } + case RoomMemberEventContent.MembershipTypes.Ban: { + if (_showBans) { + <p style="color: red;">@membership.Sender banned @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p> + } + + break; + } + case RoomMemberEventContent.MembershipTypes.Leave: { + if (membership.Sender == membership.StateKey) { + if (_showLeaves) { + <p style="color: #C66;">@membership.Sender left the room</p> + } + } + else { + if (_showKicks) { + <p style="color: darkorange;">@membership.Sender kicked @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p> + } + } + + break; + } + case RoomMemberEventContent.MembershipTypes.Knock: { + if (_showKnocks) { + <p>@membership.Sender knocked @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p> + } + + break; + } + case RoomMemberEventContent.MembershipTypes.Join: { + if (previousMemberships.TryGetValue(membership.StateKey, out var previous) + && (previous.TypedContent as RoomMemberEventContent).Membership == RoomMemberEventContent.MembershipTypes.Join) { + if (_showUpdates) { + <p style="color: #777;">@membership.Sender changed their profile</p> + } + } + else { + if (_showJoins) { + <p style="color: #6C6;">@membership.Sender joined the room @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p> + } + } + + break; + } + default: { + <b>Unknown membership @content.Membership!</b> + break; + } + } + + previousMemberships[membership.StateKey] = membership; + } + } +</details> + +<br/> +<details open> + <summary>Log</summary> + @foreach (var line in log.Reverse()) { + <pre>@line</pre> + } +</details> + +@code { + +#region Filter bindings + + private bool _chronologicalOrder = false; + + private bool ChronologicalOrder { + get => _chronologicalOrder; + set { + _chronologicalOrder = value; + StateHasChanged(); + } + } + + private bool _showJoins = true; + + private bool ShowJoins { + get => _showJoins; + set { + _showJoins = value; + StateHasChanged(); + } + } + + private bool _showLeaves = true; + + private bool ShowLeaves { + get => _showLeaves; + set { + _showLeaves = value; + StateHasChanged(); + } + } + + private bool _showUpdates = true; + + private bool ShowUpdates { + get => _showUpdates; + set { + _showUpdates = value; + StateHasChanged(); + } + } + + private bool _showKnocks = true; + + private bool ShowKnocks { + get => _showKnocks; + set { + _showKnocks = value; + StateHasChanged(); + } + } + + private bool _showInvites = true; + + private bool ShowInvites { + get => _showInvites; + set { + _showInvites = value; + StateHasChanged(); + } + } + + private bool _showKicks = true; + + private bool ShowKicks { + get => _showKicks; + set { + _showKicks = value; + StateHasChanged(); + } + } + + private bool _showBans = true; + + private bool ShowBans { + get => _showBans; + set { + _showBans = value; + StateHasChanged(); + } + } + + private string sender = ""; + + private string Sender { + get => sender; + set { + sender = value; + StateHasChanged(); + } + } + + private string user = ""; + + private string User { + get => user; + set { + user = value; + StateHasChanged(); + } + } + +#endregion + + private ObservableCollection<string> log { get; set; } = new(); + private List<StateEventResponse> Memberships { get; set; } = []; + 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(); + if (!string.IsNullOrWhiteSpace(roomId)) + await Execute(); + } + + private async Task Execute() { + Memberships.Clear(); + var room = hs.GetRoom(roomId); + var events = room.GetManyMessagesAsync(limit: int.MaxValue, chunkSize: 5000); + await foreach (var resp in events) { + var all = resp.State.Concat(resp.Chunk); + Memberships.AddRange(all.Where(x => x.Type == RoomMemberEventContent.EventId)); + + log.Add($"{resp.State.Count} state, {resp.Chunk.Count} timeline"); + } + + StateHasChanged(); + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/RoomIntersections.razor b/MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor
index 173ff01..b8baeb8 100644 --- a/MatrixUtils.Web/Pages/Tools/RoomIntersections.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor
@@ -1,4 +1,4 @@ -@page "/Tools/RoomIntersections" +@page "/Tools/Moderation/RoomIntersections" @using LibMatrix.RoomTypes @using System.Collections.ObjectModel @using LibMatrix diff --git a/MatrixUtils.Web/Pages/Tools/UserTrace.razor b/MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor
index 95fe02b..915f8dc 100644 --- a/MatrixUtils.Web/Pages/Tools/UserTrace.razor +++ b/MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor
@@ -1,12 +1,8 @@ -@page "/Tools/UserTrace" +@page "/Tools/Moderation/UserTrace" @using ArcaneLibs.Extensions @using LibMatrix.RoomTypes @using System.Collections.ObjectModel @using LibMatrix -@using System.Collections.Frozen -@using LibMatrix.EventTypes.Spec.State -@using LibMatrix.Filters -@using MatrixUtils.Abstractions <h3>User Trace</h3> <hr/> diff --git a/MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor b/MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor
index 667b518..667b518 100644 --- a/MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor +++ b/MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor
diff --git a/MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor b/MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor
index a2ad388..a2ad388 100644 --- a/MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor +++ b/MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor
diff --git a/MatrixUtils.Web/Pages/Tools/ViewAccountData.razor b/MatrixUtils.Web/Pages/Tools/User/ViewAccountData.razor
index d8b02bb..d8b02bb 100644 --- a/MatrixUtils.Web/Pages/Tools/ViewAccountData.razor +++ b/MatrixUtils.Web/Pages/Tools/User/ViewAccountData.razor