From ddb5a61b0fd234b436c0406ab57e38d67429c6b8 Mon Sep 17 00:00:00 2001 From: Rory& Date: Tue, 13 May 2025 08:17:26 +0200 Subject: Initial commit --- MiniUtils.Core/PolicyStore.cs | 104 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 MiniUtils.Core/PolicyStore.cs (limited to 'MiniUtils.Core/PolicyStore.cs') diff --git a/MiniUtils.Core/PolicyStore.cs b/MiniUtils.Core/PolicyStore.cs new file mode 100644 index 0000000..f2aa0fc --- /dev/null +++ b/MiniUtils.Core/PolicyStore.cs @@ -0,0 +1,104 @@ +using System.Diagnostics; +using LibMatrix; +using LibMatrix.EventTypes.Spec.State.Policy; +using Microsoft.Extensions.Logging; + +namespace MiniUtils.Core; + +public class PolicyStore(ILogger logger) { + public Dictionary AllPolicies { get; } = []; + +#region Single policy events + + /// + /// Fired when any policy event is received + /// + public List> OnPolicyReceived { get; } = []; + + /// + /// Fired when a new policy is added + /// + public List> OnPolicyAdded { get; } = []; + + /// + /// Fired when a policy is updated, without being removed. + /// + public List> OnPolicyUpdated { get; } = []; + + /// + /// Fired when a policy is removed. + /// + public List> OnPolicyRemoved { get; } = []; + +#endregion + +#region Bulk policy events + + /// + /// Fired when any policy event is received + /// + public List NewPolicies, + List<(StateEventResponse Old, StateEventResponse New)> UpdatedPolicies, + List<(StateEventResponse Old, StateEventResponse New)> RemovedPolicies), Task>> OnPoliciesChanged { get; } = []; + +#endregion + + public async Task AddPoliciesAsync(IEnumerable events) { + var policyEvents = events + .Where(evt => evt.TypedContent is PolicyRuleEventContent) + .ToList(); + List newPolicies = new(); + List<(StateEventResponse Old, StateEventResponse New)> updatedPolicies = new(); + List<(StateEventResponse Old, StateEventResponse New)> removedPolicies = new(); + + var sw = Stopwatch.StartNew(); + try { + foreach (var evt in policyEvents) { + var eventKey = $"{evt.RoomId}:{evt.Type}:{evt.StateKey}"; + if (evt.TypedContent is not PolicyRuleEventContent policy) continue; + if (policy.GetNormalizedRecommendation() is "m.ban") { + if (AllPolicies.TryGetValue(eventKey, out var oldContent)) + updatedPolicies.Add((oldContent, evt)); + else + newPolicies.Add(evt); + AllPolicies[eventKey] = evt; + } + else if (AllPolicies.Remove(eventKey, out var oldContent)) + removedPolicies.Add((oldContent, evt)); + } + } + catch (Exception e) { + Console.WriteLine(e); + } + + logger.LogInformation("Processed {Count} policies in {Elapsed}", policyEvents.Count, sw.Elapsed); + + + // execute all the callbacks in parallel, as much as possible... + await Task.WhenAll( + Task.WhenAll( + policyEvents.Select(evt => + Task.WhenAll(OnPolicyReceived.Select(callback => callback(evt)).ToList()) + ) + ), + Task.WhenAll( + newPolicies.Select(evt => + Task.WhenAll(OnPolicyAdded.Select(callback => callback(evt)).ToList()) + ) + ), + Task.WhenAll( + updatedPolicies.Select(evt => + Task.WhenAll(OnPolicyUpdated.Select(callback => callback(evt.Old, evt.New)).ToList()) + ) + ), + Task.WhenAll( + removedPolicies.Select(evt => + Task.WhenAll(OnPolicyRemoved.Select(callback => callback(evt.Old, evt.New)).ToList()) + ) + ), + Task.WhenAll(OnPoliciesChanged.Select(callback => callback((newPolicies, updatedPolicies, removedPolicies))).ToList()) + ); + } + + private async Task AddPolicyAsync(StateEventResponse evt) { } +} \ No newline at end of file -- cgit 1.5.1