diff options
Diffstat (limited to 'MatrixUtils.Web/Pages/Moderation')
-rw-r--r-- | MatrixUtils.Web/Pages/Moderation/DraupnirProtectedRoomsEditor.razor | 97 | ||||
-rw-r--r-- | MatrixUtils.Web/Pages/Moderation/UserRoomHistory.razor | 115 |
2 files changed, 212 insertions, 0 deletions
diff --git a/MatrixUtils.Web/Pages/Moderation/DraupnirProtectedRoomsEditor.razor b/MatrixUtils.Web/Pages/Moderation/DraupnirProtectedRoomsEditor.razor new file mode 100644 index 0000000..fb4f9bf --- /dev/null +++ b/MatrixUtils.Web/Pages/Moderation/DraupnirProtectedRoomsEditor.razor @@ -0,0 +1,97 @@ +@page "/Moderation/DraupnirProtectedRoomsEditor" +@using System.Text.Json.Serialization +@using MatrixUtils.Abstractions +@using System.Collections.Frozen +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.RoomTypes +<h3>Edit Draupnir protected rooms</h3> +<hr/> + +@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(); + foreach (var room in await hs.GetJoinedRooms()) { + 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(); + } + } + + 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/Moderation/UserRoomHistory.razor b/MatrixUtils.Web/Pages/Moderation/UserRoomHistory.razor new file mode 100644 index 0000000..e4eea83 --- /dev/null +++ b/MatrixUtils.Web/Pages/Moderation/UserRoomHistory.razor @@ -0,0 +1,115 @@ +@page "/Moderation/UserRoomHistory/{UserId}" +@using LibMatrix.Homeservers +@using LibMatrix +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.RoomTypes +@using ArcaneLibs.Extensions +@using MatrixUtils.Abstractions +<h3>UserRoomHistory</h3> + +<span>Enter mxid: </span> +<FancyTextBox @bind-Value="@UserId"></FancyTextBox> + +@if (string.IsNullOrWhiteSpace(UserId)) { + <p>UserId is null!</p> +} +else { + <p>Checked @checkedRooms.Count so far...</p> + @if (currentHs is not null) { + <p>Checking rooms from @currentHs.UserId's perspective</p> + } + else if (checkedRooms.Count > 1) { + <p>Done!</p> + } + @foreach (var (state, rooms) in matchingStates) { + <u>@state</u> + <br/> + @foreach (var roomInfo in rooms) { + <RoomListItem RoomInfo="roomInfo" LoadData="true"></RoomListItem> + } + } +} + +@code { + private string? _userId; + + [Parameter] + public string? UserId { + get => _userId; + set { + _userId = value; + FindMember(value); + } + } + + private List<AuthenticatedHomeserverGeneric> 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<string, List<RoomInfo>> matchingStates = new(); + public List<string> 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 = 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>(RoomMemberEventContent.EventId, mxid)); + } + +} \ No newline at end of file |