From ede3857084bc7c6e65b7d36cbf913b09596e2787 Mon Sep 17 00:00:00 2001
From: Rory&
Date: Mon, 8 Jan 2024 13:55:15 +0100
Subject: Internal changes to policy list viewer (extensibility), fix
duplicating change handler for room list page (performance), use /state in
room list page before sync
---
MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor | 336 +++++++++++++----------
1 file changed, 187 insertions(+), 149 deletions(-)
(limited to 'MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor')
diff --git a/MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor b/MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor
index 846d1cb..dbe0648 100644
--- a/MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor
+++ b/MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor
@@ -4,184 +4,199 @@
@using ArcaneLibs.Extensions
@using LibMatrix.EventTypes.Spec.State
@using LibMatrix.EventTypes.Spec.State.Policy
+@using System.Diagnostics
+@using System.Diagnostics.CodeAnalysis
+@using LibMatrix.Extensions
+@using LibMatrix.Responses
Policy list editor - Editing @RoomId
- This policy list contains @PolicyEvents.Count(x => x.Type == "m.policy.rule.server") server bans,
- @PolicyEvents.Count(x => x.Type == "m.policy.rule.room") room bans and
- @PolicyEvents.Count(x => x.Type == "m.policy.rule.user") user bans.
+ This policy list contains @GetPolicyCount(typeof(ServerPolicyRuleEventContent)) server bans,
+ @GetPolicyCount(typeof(RoomPolicyRuleEventContent)) room bans and
+ @GetPolicyCount(typeof(UserPolicyRuleEventContent)) user bans.
+ @foreach (var (key, value) in PolicyEventsByType) {
+
@key.Name: @value.Count
+ }
-Enable avatars (WILL EXPOSE YOUR IP TO TARGET HOMESERVERS!)
-
+Enable avatars (WILL EXPOSE YOUR IP TO TARGET HOMESERVERS!)
-@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.server")) {
+Server policies
+
+@if (!GetPolicyEventsByType(typeof(ServerPolicyRuleEventContent)).Any()) {
No server policies
}
else {
- Server policies
-
-
+
-
- Server
- Reason
- Expires
- Actions
-
-
-
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && (x.TypedContent as PolicyRuleEventContent).Entity is not null)) {
- var policyData = policyEvent.TypedContent as PolicyRuleEventContent;
- Entity: @policyData.Entity State: @policyEvent.StateKey
- @policyData.Reason
-
- @policyData.ExpiryDateTime
-
-
- await RemovePolicyAsync(policyEvent)" *@>Edit
- @* await RemovePolicyAsync(policyEvent)" #1#>Remove *@
-
+ Server
+ Reason
+ Expires
+ Actions
- }
+
+
+ @foreach (var policyEvent in GetValidPolicyEventsByType(typeof(ServerPolicyRuleEventContent))) {
+ var policyData = policyEvent.TypedContent as PolicyRuleEventContent;
+
+
+ Entity: @policyData.Entity
+ State: @policyEvent.StateKey
+
+ @policyData.Reason
+
+ @policyData.ExpiryDateTime
+
+
+ await RemovePolicyAsync(policyEvent)" *@>Edit
+ @* await RemovePolicyAsync(policyEvent)" #1#>Remove *@
+
+
+ }
- Redacted events
-
+ Redacted or invalid events
+
-
- State key
- Serialised Contents
-
-
-
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && (x.TypedContent as PolicyRuleEventContent).Entity == null)) {
- var policyData = policyEvent.TypedContent as PolicyRuleEventContent;
- @policyEvent.StateKey
- @policyEvent.RawContent.ToJson(false, true)
+ State key
+ Serialised Contents
- }
+
+
+ @foreach (var policyEvent in GetInvalidPolicyEventsByType(typeof(ServerPolicyRuleEventContent))) {
+
+ @policyEvent.StateKey
+ @policyEvent.RawContent.ToJson(false, true)
+
+ }
}
-@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.room")) {
+Room policies
+
+@if (!GetPolicyEventsByType(typeof(RoomPolicyRuleEventContent)).Any()) {
No room policies
}
else {
- Room policies
-
-
+
-
- Room
- Reason
- Expires
- Actions
-
-
-
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && (x.TypedContent as PolicyRuleEventContent).Entity is not null)) {
- var policyData = policyEvent.TypedContent as PolicyRuleEventContent;
- Entity: @policyData.Entity State: @policyEvent.StateKey
- @policyData.Reason
-
- @policyData.ExpiryDateTime
-
-
- await RemovePolicyAsync(policyEvent)" *@>Remove
-
+ Room
+ Reason
+ Expires
+ Actions
- }
+
+
+ @foreach (var policyEvent in GetValidPolicyEventsByType(typeof(RoomPolicyRuleEventContent))) {
+ var policyData = policyEvent.TypedContent as PolicyRuleEventContent;
+
+ Entity: @policyData.Entity State: @policyEvent.StateKey
+ @policyData.Reason
+
+ @policyData.ExpiryDateTime
+
+
+ await RemovePolicyAsync(policyEvent)" *@>Remove
+
+
+ }
- Redacted events
-
+ Redacted or invalid events
+
-
- State key
- Serialised Contents
-
-
-
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && (x.TypedContent as PolicyRuleEventContent).Entity == null)) {
- @policyEvent.StateKey
- @policyEvent.RawContent!.ToJson(false, true)
+ State key
+ Serialised Contents
- }
+
+
+ @foreach (var policyEvent in GetInvalidPolicyEventsByType(typeof(RoomPolicyRuleEventContent))) {
+
+ @policyEvent.StateKey
+ @policyEvent.RawContent!.ToJson(false, true)
+
+ }
}
-@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.user")) {
+User policies
+
+@if (!GetPolicyEventsByType(typeof(UserPolicyRuleEventContent)).Any()) {
No user policies
}
else {
- User policies
-
-
+
-
- @if (_enableAvatars) {
-
- }
- User
- Reason
- Expires
- Actions
-
-
-
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && (x.TypedContent as PolicyRuleEventContent).Entity is not null)) {
- var policyData = policyEvent.TypedContent as PolicyRuleEventContent;
- @if (_enableAvatars) {
-
-
-
+ @if (EnableAvatars) {
+
}
- Entity: @string.Join("", policyData.Entity.Take(64)) State: @string.Join("", policyEvent.StateKey.Take(64))
- @policyData.Reason
-
- @policyData.ExpiryDateTime
-
-
- await RemovePolicyAsync(policyEvent)" *@>Remove
-
+ User
+ Reason
+ Expires
+ Actions
- }
+
+
+ @foreach (var policyEvent in GetValidPolicyEventsByType(typeof(UserPolicyRuleEventContent))) {
+ var policyData = policyEvent.TypedContent as PolicyRuleEventContent;
+
+ @if (EnableAvatars) {
+
+ @if (Avatars.ContainsKey(policyData.Entity)) {
+
+ }
+
+ }
+ Entity: @string.Join("", policyData.Entity.Take(64)) State: @string.Join("", policyEvent.StateKey.Take(64))
+ @policyData.Reason
+
+ @policyData.ExpiryDateTime
+
+
+ await RemovePolicyAsync(policyEvent)" *@>Remove
+
+
+ }
- Redacted events
-
+ Redacted or invalid events
+
-
- State key
- Serialised Contents
-
-
-
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && (x.TypedContent as PolicyRuleEventContent).Entity == null)) {
- @policyEvent.StateKey
- @policyEvent.RawContent.ToJson(false, true)
+ State key
+ Serialised Contents
- }
+
+
+ @foreach (var policyEvent in GetInvalidPolicyEventsByType(typeof(UserPolicyRuleEventContent))) {
+
+ @policyEvent.StateKey
+ @policyEvent.RawContent.ToJson(false, true)
+
+ }
}
-
-
@code {
+
+#if DEBUG
+ private const bool Debug = true;
+#else
+ private const bool Debug = false;
+#endif
+
//get room list
// - sync withroom list filter
// Type = support.feline.msc3784
@@ -192,18 +207,28 @@ else {
private bool _enableAvatars;
- static readonly Dictionary avatars = new();
- static readonly Dictionary servers = new();
+ static readonly Dictionary Avatars = new();
+ // static readonly Dictionary Servers = new();
- public static List PolicyEvents { get; set; } = new();
+ // private static List PolicyEvents { get; set; } = new();
+ private Dictionary> PolicyEventsByType { get; set; } = new();
+
+ public bool EnableAvatars {
+ get => _enableAvatars;
+ set {
+ _enableAvatars = value;
+ if (value) GetAllAvatars();
+ }
+ }
protected override async Task OnInitializedAsync() {
+ var sw = Stopwatch.StartNew();
await base.OnInitializedAsync();
var hs = await MRUStorage.GetCurrentSessionOrNavigate();
if (hs is null) return;
RoomId = RoomId.Replace('~', '.');
await LoadStatesAsync();
- Console.WriteLine("Policy list editor initialized!");
+ Console.WriteLine($"Policy list editor initialized in {sw.Elapsed}!");
}
private async Task LoadStatesAsync() {
@@ -214,39 +239,52 @@ else {
var states = room.GetFullStateAsync();
await foreach (var state in states) {
- if (!state.Type.StartsWith("m.policy.rule")) continue;
- PolicyEvents.Add(state);
+ if (state is null) continue;
+ if (!state.MappedType.IsAssignableTo(typeof(PolicyRuleEventContent))) continue;
+ if (!PolicyEventsByType.ContainsKey(state.MappedType)) PolicyEventsByType.Add(state.MappedType, new());
+ PolicyEventsByType[state.MappedType].Add(state);
}
-
- // var stateEventsQuery = await room.GetStateAsync("");
- // var stateEvents = stateEventsQuery.Value.Deserialize>();
- // PolicyEvents = stateEvents.Where(x => x.Type.StartsWith("m.policy.rule"))
- // .Select(x => JsonSerializer.Deserialize(JsonSerializer.Serialize(x))).ToList();
StateHasChanged();
}
- private async Task GetAvatar(string userId) {
- try {
- if (avatars.ContainsKey(userId)) return;
- var hs = userId.Split(':')[1];
- var server = servers.ContainsKey(hs) ? servers[hs] : new RemoteHomeserver(userId.Split(':')[1]);
- if (!servers.ContainsKey(hs)) servers.Add(hs, server);
- var profile = await server.GetProfileAsync(userId);
- avatars.Add(userId, await hsResolver.ResolveMediaUri(server.BaseUrl, profile.AvatarUrl));
- servers.Add(userId, server);
+ private async Task GetAllAvatars() {
+ // if (!_enableAvatars) return;
+ Console.WriteLine("Getting avatars...");
+ var users = GetValidPolicyEventsByType(typeof(UserPolicyRuleEventContent)).Select(x => x.RawContent!["entity"]!.GetValue()).Where(x => x.Contains(':') && !x.Contains("*")).ToList();
+ Console.WriteLine($"Got {users.Count} users!");
+ var usersByHomeServer = users.GroupBy(x => x!.Split(':')[1]).ToDictionary(x => x.Key!, x => x.ToList());
+ Console.WriteLine($"Got {usersByHomeServer.Count} homeservers!");
+ var homeserverTasks = usersByHomeServer.Keys.Select(x => RemoteHomeserver.TryCreate(x)).ToAsyncEnumerable();
+ await foreach (var server in homeserverTasks) {
+ if (server is null) continue;
+ var profileTasks = usersByHomeServer[server.BaseUrl].Select(x => TryGetProfile(server, x)).ToList();
+ await Task.WhenAll(profileTasks);
+ profileTasks.RemoveAll(x => x.Result is not { Value: { AvatarUrl: not null } });
+ foreach (var profile in profileTasks.Select(x => x.Result!.Value)) {
+ // if (profile is null) continue;
+ if (!string.IsNullOrWhiteSpace(profile.Value.AvatarUrl)) {
+ var url = await hsResolver.ResolveMediaUri(server.BaseUrl, profile.Value.AvatarUrl);
+ Avatars.TryAdd(profile.Key, url);
+ }
+ else Avatars.TryAdd(profile.Key, null);
+ }
StateHasChanged();
}
- catch {
- // ignored
- }
}
- private async Task GetAllAvatars() {
- foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && (x.TypedContent as PolicyRuleEventContent).Entity is not null)) {
- await GetAvatar((policyEvent.TypedContent as PolicyRuleEventContent).Entity);
+ private async Task?> TryGetProfile(RemoteHomeserver server, string mxid) {
+ try {
+ return new KeyValuePair(mxid, await server.GetProfileAsync(mxid));
+ }
+ catch {
+ return null;
}
- StateHasChanged();
}
-}
+ private List GetPolicyEventsByType(Type type) => PolicyEventsByType.ContainsKey(type) ? PolicyEventsByType[type] : [];
+ private List GetValidPolicyEventsByType(Type type) => GetPolicyEventsByType(type).Where(x => !string.IsNullOrWhiteSpace(x.RawContent?["entity"]?.GetValue())).ToList();
+ private List GetInvalidPolicyEventsByType(Type type) => GetPolicyEventsByType(type).Where(x => string.IsNullOrWhiteSpace(x.RawContent?["entity"]?.GetValue())).ToList();
+ private int GetPolicyCount(Type type) => PolicyEventsByType.ContainsKey(type) ? PolicyEventsByType[type].Count : 0;
+
+}
\ No newline at end of file
--
cgit 1.4.1