From 03313562d21d5db9bf6a14ebbeab80e06c883d3a Mon Sep 17 00:00:00 2001 From: Rory& Date: Wed, 24 Jan 2024 02:31:56 +0100 Subject: MRU->RMU, fixes, cleanup --- MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor | 84 +++++++++++++++ .../Pages/Tools/KnownHomeserverList.razor | 54 ++++++++++ MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor | 110 ++++++++++++++++++++ MatrixUtils.Web/Pages/Tools/MediaLocator.razor | 111 ++++++++++++++++++++ MatrixUtils.Web/Pages/Tools/SpaceDebug.razor | 113 +++++++++++++++++++++ MatrixUtils.Web/Pages/Tools/ToolsIndex.razor | 8 ++ 6 files changed, 480 insertions(+) create mode 100644 MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor create mode 100644 MatrixUtils.Web/Pages/Tools/KnownHomeserverList.razor create mode 100644 MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor create mode 100644 MatrixUtils.Web/Pages/Tools/MediaLocator.razor create mode 100644 MatrixUtils.Web/Pages/Tools/SpaceDebug.razor create mode 100644 MatrixUtils.Web/Pages/Tools/ToolsIndex.razor (limited to 'MatrixUtils.Web/Pages/Tools') diff --git a/MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor b/MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor new file mode 100644 index 0000000..31f3f23 --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor @@ -0,0 +1,84 @@ +@page "/Tools/CopyPowerlevel" +@using System.Diagnostics +@using ArcaneLibs.Extensions +@using LibMatrix +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.Homeservers +@using LibMatrix.RoomTypes +

Copy powerlevel

+
+ +

Users:

+@foreach (var hs in hss) { +

@hs.WhoAmI.UserId

+} + +
+Execute +
+@foreach (var line in Enumerable.Reverse(log)) { +

@line

+} + +@code { + private List log { get; set; } = new(); + List hss { get; set; } = new(); + + 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(); + } + + private async Task Execute() { + foreach (var hs in hss) { + var rooms = await hs.GetJoinedRooms(); + var tasks = rooms.Select(x=>Execute(hs, x)).ToAsyncEnumerable(); + await foreach (var a in tasks) { + if (!string.IsNullOrWhiteSpace(a)) { + log.Add(a); + StateHasChanged(); + } + } + } + } + + private async Task Execute(AuthenticatedHomeserverGeneric hs, GenericRoom room) { + try { + var pls = await room.GetPowerLevelsAsync(); + // if (pls.GetUserPowerLevel(hs.WhoAmI.UserId) == pls.UsersDefault) return "I am default PL in " + room.RoomId; + if (!pls.UserHasStatePermission(hs.WhoAmI.UserId, RoomPowerLevelEventContent.EventId)) return "I do not have permission to send PL in " + room.RoomId; + foreach (var ahs in hss) { + if (pls.GetUserPowerLevel(hs.WhoAmI.UserId) == pls.GetUserPowerLevel(ahs.WhoAmI.UserId)) { + log.Add("I am same PL in " + room.RoomId); + continue; + } + + pls.SetUserPowerLevel(ahs.WhoAmI.UserId, pls.GetUserPowerLevel(hs.WhoAmI.UserId)); + await room.SendStateEventAsync(RoomPowerLevelEventContent.EventId, pls); + log.Add($"Updated powerlevel of {room.RoomId} to {pls.GetUserPowerLevel(ahs.WhoAmI.UserId)}"); + } + + } + catch (MatrixException e) { + return $"Failed to update PLs in {room.RoomId}: {e.Message}"; + } + catch (Exception e) { + return $"Failed to update PLs in {room.RoomId}: {e.Message}"; + } + StateHasChanged(); + return ""; + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/KnownHomeserverList.razor b/MatrixUtils.Web/Pages/Tools/KnownHomeserverList.razor new file mode 100644 index 0000000..f73215d --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/KnownHomeserverList.razor @@ -0,0 +1,54 @@ +@page "/Tools/KnownHomeserverList" +@using System.Diagnostics +@using ArcaneLibs.Extensions +@using LibMatrix.Homeservers +@using LibMatrix.RoomTypes +

Known Homeserver List

+
+ +@if (!IsFinished) { +

+ Loading... +

+} + +@foreach (var (homeserver, members) in counts.OrderByDescending(x => x.Value)) { +

@homeserver - @members

+} +
+ +@code { + Dictionary> homeservers { get; set; } = new(); + Dictionary counts { get; set; } = new(); + // List Homeservers = new(); + bool IsFinished { get; set; } + // HomeserverInfoQueryProgress QueryProgress { get; set; } = new(); + AuthenticatedHomeserverGeneric? hs { get; set; } + + protected override async Task OnInitializedAsync() { + hs = await RMUStorage.GetCurrentSessionOrNavigate(); + if (hs is null) return; + var fetchTasks = (await hs.GetJoinedRooms()).Select(x=>x.GetMembersByHomeserverAsync()).ToAsyncEnumerable(); + await foreach (var result in fetchTasks) { + foreach (var (resHomeserver, resMembers) in result) { + if (!homeservers.TryAdd(resHomeserver, resMembers)) { + homeservers[resHomeserver].AddRange(resMembers); + } + counts[resHomeserver] = homeservers[resHomeserver].Count; + } + // StateHasChanged(); + // await Task.Delay(250); + } + + foreach (var resHomeserver in homeservers.Keys) { + homeservers[resHomeserver] = homeservers[resHomeserver].Distinct().ToList(); + counts[resHomeserver] = homeservers[resHomeserver].Count; + } + + IsFinished = true; + StateHasChanged(); + Console.WriteLine("Rerendered!"); + await base.OnInitializedAsync(); + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor b/MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor new file mode 100644 index 0000000..6efb0ae --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor @@ -0,0 +1,110 @@ +@page "/Tools/MassRoomJoin" +@using System.Diagnostics +@using ArcaneLibs.Extensions +@using LibMatrix +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.Homeservers +@using LibMatrix.RoomTypes +

Mass join room

+
+

Room:

+ + +

Users:

+@foreach (var hs in hss) { +

@hs.WhoAmI.UserId

+} + +
+Execute +
+@foreach (var line in Enumerable.Reverse(log)) { +

@line

+} + +@code { + private List log { get; set; } = new(); + List hss { get; set; } = new(); + string roomId { 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(); + } + + private async Task Execute() { + // foreach (var hs in hss) { + // var rooms = await hs.GetJoinedRooms(); + var tasks = hss.Select(ExecuteInvite).ToAsyncEnumerable(); + await foreach (var a in tasks) { + if (!string.IsNullOrWhiteSpace(a)) { + log.Add(a); + StateHasChanged(); + } + } + tasks = hss.Select(ExecuteJoin).ToAsyncEnumerable(); + await foreach (var a in tasks) { + if (!string.IsNullOrWhiteSpace(a)) { + log.Add(a); + StateHasChanged(); + } + } + // } + } + + private async Task ExecuteInvite(AuthenticatedHomeserverGeneric hs) { + var room = hs.GetRoom(roomId); + try { + try { + var joinRule = await room.GetJoinRuleAsync(); + if (joinRule.JoinRule == RoomJoinRulesEventContent.JoinRules.Public) return "Room is public, no invite needed"; + } + catch { } + var pls = await room.GetPowerLevelsAsync(); + if (pls.GetUserPowerLevel(hs.WhoAmI.UserId) < pls.Invite) return "I do not have permission to send invite in " + room.RoomId; + await room.InviteUsersAsync(hss.Select(x => x.WhoAmI.UserId).ToList()); + log.Add($"Invited to {room.RoomId} to {pls.GetUserPowerLevel(hs.WhoAmI.UserId)}"); + } + catch (MatrixException e) { + return $"Failed to invite in {room.RoomId}: {e.Message}"; + } + catch (Exception e) { + return $"Failed to invite in {room.RoomId}: {e.Message}"; + } + StateHasChanged(); + return ""; + } + + private async Task ExecuteJoin(AuthenticatedHomeserverGeneric hs) { + var room = hs.GetRoom(roomId); + try { + try { + var mse = await room.GetStateOrNullAsync(RoomMemberEventContent.EventId, hs.WhoAmI.UserId); + if (mse?.Membership == "join") return $"User {hs.WhoAmI.UserId} already in room"; + } + catch { } + await room.JoinAsync(); + } + catch (MatrixException e) { + return $"Failed to join {hs.WhoAmI.UserId} to {room.RoomId}: {e.Message}"; + } + catch (Exception e) { + return $"Failed to join {hs.WhoAmI.UserId} to {room.RoomId}: {e.Message}"; + } + StateHasChanged(); + return ""; + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Pages/Tools/MediaLocator.razor b/MatrixUtils.Web/Pages/Tools/MediaLocator.razor new file mode 100644 index 0000000..38c9b71 --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/MediaLocator.razor @@ -0,0 +1,111 @@ +@page "/Tools/MediaLocator" +@using LibMatrix.Homeservers +@inject HttpClient Http +

Media locator

+
+ +This is going to expose your IP address to all these homeservers! +
+ Checked homeserver list (@homeservers.Count entries) +
    + @foreach (var hs in homeservers) { +
  • @hs
  • + } +
+
+ +
+MXC URL: + + + +@if (successResults.Count > 0) { +

Successes

+
    + @foreach (var result in successResults) { +
  • @result
  • + } +
+} + +@if (errorResults.Count > 0) { +

Errors

+
    + @foreach (var result in errorResults) { +
  • @result
  • + } +
+} + + +@code { + string mxcUrl { get; set; } + readonly List successResults = new(); + readonly List errorResults = new(); + readonly List homeservers = new(); + + protected override async Task OnInitializedAsync() { + await base.OnInitializedAsync(); + homeservers.AddRange(new[] { + "matrix.org", + "feline.support", + "rory.gay", + "the-apothecary.club", + "envs.net", + "projectsegfau.lt" + }); + } + + Task executeSearch() { + var sem = new SemaphoreSlim(128, 128); + homeservers.ForEach(async hs => { + await sem.WaitAsync(); + var httpClient = new HttpClient { BaseAddress = new Uri(hs) }; + httpClient.Timeout = TimeSpan.FromSeconds(5); + var rmu = mxcUrl.Replace("mxc://", $"{hs}/_matrix/media/v3/download/"); + try { + var res = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, rmu)); + if (res.IsSuccessStatusCode) { + successResults.Add($"{hs}: found - {res.Content.Headers.ContentLength} bytes"); + StateHasChanged(); + return; + } + errorResults.Add($"Error: {hs} - {res.StatusCode}\n" + await res.Content.ReadAsStringAsync()); + } + catch (Exception e) { + errorResults.Add($"Error: {e}"); + } + finally { + sem.Release(); + } + StateHasChanged(); + }); + return Task.CompletedTask; + } + + async Task addMoreHomeservers() { + var res = await Http.GetAsync("/homeservers.txt"); + var content = await res.Content.ReadAsStringAsync(); + homeservers.Clear(); + var lines = content.Split("\n"); + + var rhs = new RemoteHomeserver("rory.gay"); + var sem = new SemaphoreSlim(128, 128); + lines.ToList().ForEach(async line => { + await sem.WaitAsync(); + try { + homeservers.Add((await hsResolver.ResolveHomeserverFromWellKnown(line)).Client); + StateHasChanged(); + } + catch (Exception e) { + Console.WriteLine(e); + } + finally { + sem.Release(); + } + }); + + StateHasChanged(); + } + +} diff --git a/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor b/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor new file mode 100644 index 0000000..5d9b8eb --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor @@ -0,0 +1,113 @@ +@page "/Tools/SpaceDebug" +@using LibMatrix.Filters +@using LibMatrix.Helpers +

SpaceDebug

+
+ +

@Status

+ +Has parent: +
+ +@foreach (var (roomId, parents) in SpaceParents) { +

@roomId's parents

+
    + @foreach (var parent in parents) { +
  • @parent
  • + } +
+} + +Space children: + +@foreach (var (roomId, children) in SpaceChildren) { +

@roomId's children

+
    + @foreach (var child in children) { +
  • @child
  • + } +
+} + +@code { + private string _status = "Loading..."; + + public string Status { + get => _status; + set { + _status = value; + StateHasChanged(); + } + } + + public Dictionary> SpaceChildren { get; set; } = new(); + public Dictionary> SpaceParents { get; set; } = new(); + + protected override async Task OnInitializedAsync() { + Status = "Getting homeserver..."; + var hs = await RMUStorage.GetCurrentSessionOrNavigate(); + if (hs is null) return; + + var syncHelper = new SyncHelper(hs) { + Filter = new SyncFilter() { + Presence = new(0), + Room = new() { + AccountData = new(limit: 0), + Ephemeral = new(limit: 0), + State = new(limit: 1000, types: new() { "m.space.child", "m.space.parent" }), + Timeline = new(limit: 0) + }, + AccountData = new(limit: 0) + } + }; + + Status = "Syncing..."; + + var syncs = syncHelper.EnumerateSyncAsync(); + await foreach (var sync in syncs) { + if (sync is null) { + Status = "Sync failed"; + continue; + } + + if (sync.Rooms is null) { + Status = "No rooms in sync..."; + break; + } + + if (sync.Rooms.Join is null) { + Status = "No joined rooms in sync..."; + break; + } + + if (sync.Rooms.Join.Count == 0) { + Status = "Joined rooms list was empty..."; + break; + } + + // nextBatch = sync.NextBatch; + foreach (var (roomId, data) in sync.Rooms!.Join!) { + data.State?.Events?.ForEach(e => { + if (e.Type == "m.space.child") { + if (!SpaceChildren.ContainsKey(roomId)) SpaceChildren[roomId] = new(); + if (e.RawContent is null) e.StateKey += " (null)"; + else if (e.RawContent.Count == 0) e.StateKey += " (empty)"; + SpaceChildren[roomId].Add(e.StateKey); + } + if (e.Type == "m.space.parent") { + if (!SpaceParents.ContainsKey(roomId)) SpaceParents[roomId] = new(); + if (e.RawContent is null) e.StateKey += " (null)"; + else if (e.RawContent.Count == 0) e.StateKey += " (empty)"; + SpaceParents[roomId].Add(e.StateKey); + } + }); + } + Status = $"Synced {sync.Rooms.Join.Count} rooms, found {SpaceChildren.Count} spaces, {SpaceParents.Count} parents"; + } + Status = $"Synced: found {SpaceChildren.Count}->{SpaceChildren.Sum(x => x.Value.Count)} spaces, {SpaceParents.Count}->{SpaceParents.Sum(x => x.Value.Count)} parents!"; + + await base.OnInitializedAsync(); + } + + +} diff --git a/MatrixUtils.Web/Pages/Tools/ToolsIndex.razor b/MatrixUtils.Web/Pages/Tools/ToolsIndex.razor new file mode 100644 index 0000000..f4092d7 --- /dev/null +++ b/MatrixUtils.Web/Pages/Tools/ToolsIndex.razor @@ -0,0 +1,8 @@ +@page "/Tools" +

Other tools

+ +Copy highest powerlevel across all session
+Find all homeservers you share a room with
+Join room across all session
+Locate lost media
+Debug space relationships
-- cgit 1.5.1