about summary refs log tree commit diff
path: root/MatrixAntiDmSpam.Core/PolicyExecutor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixAntiDmSpam.Core/PolicyExecutor.cs')
-rw-r--r--MatrixAntiDmSpam.Core/PolicyExecutor.cs88
1 files changed, 84 insertions, 4 deletions
diff --git a/MatrixAntiDmSpam.Core/PolicyExecutor.cs b/MatrixAntiDmSpam.Core/PolicyExecutor.cs

index 4dcaf2b..23d70a8 100644 --- a/MatrixAntiDmSpam.Core/PolicyExecutor.cs +++ b/MatrixAntiDmSpam.Core/PolicyExecutor.cs
@@ -1,11 +1,14 @@ using System.Diagnostics; using ArcaneLibs.Attributes; using ArcaneLibs.Extensions; +using LibMatrix; +using LibMatrix.EventTypes.Spec; using LibMatrix.EventTypes.Spec.State.Policy; using LibMatrix.Helpers; using LibMatrix.Homeservers; using LibMatrix.RoomTypes; using LibMatrix.Utilities.Bot.Interfaces; +using MatrixAntiDmSpam.Core.Classes; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -21,7 +24,11 @@ public class PolicyExecutor( public Task StartAsync(CancellationToken cancellationToken) { roomInviteHandler.OnInviteReceived.Add(CheckPoliciesAgainstInvite); - policyStore.OnPolicyUpdated.Add(CheckPolicyAgainstOutstandingInvites); + policyStore.OnPolicyAdded.Add(CheckPolicyAgainstOutstandingInvites); + if (config.IgnoreBannedUsers) { + policyStore.OnPoliciesChanged.Add(UpdateIgnoreList); + } + return Task.CompletedTask; } @@ -29,6 +36,76 @@ public class PolicyExecutor( return Task.CompletedTask; } +#region Feature: Manage ignore list + + private async Task UpdateIgnoreList(( + List<StateEventResponse> NewPolicies, + List<(StateEventResponse Old, StateEventResponse New)> UpdatedPolicies, + List<(StateEventResponse Old, StateEventResponse New)> RemovedPolicies) updates + ) { + var ignoreListContent = await homeserver.GetIgnoredUserListAsync(); + + foreach (var newEvent in updates.NewPolicies) { + var content = newEvent.TypedContent as PolicyRuleEventContent; + if (content.Entity is null || content.IsGlobRule()) continue; + if (content.GetNormalizedRecommendation() != "m.ban") continue; + + var policyEventReference = new MadsIgnoreMetadataContent.PolicyEventReference() { + Type = newEvent.Type, + RoomId = newEvent.RoomId, + StateKey = newEvent.StateKey! + }; + + if (ignoreListContent.IgnoredUsers.TryGetValue(content.Entity, out var existingRule)) { + if (existingRule.AdditionalData?.ContainsKey(MadsIgnoreMetadataContent.EventId) ?? false) { + var existingMetadata = existingRule.GetAdditionalData<MadsIgnoreMetadataContent>(MadsIgnoreMetadataContent.EventId); + existingMetadata.Policies.Add(policyEventReference); + } + else { + existingRule.AdditionalData ??= new(); + existingRule.AdditionalData.Add(MadsIgnoreMetadataContent.EventId, new MadsIgnoreMetadataContent { + WasUserAdded = true, + Policies = [policyEventReference] + }); + } + } + else { + ignoreListContent.IgnoredUsers[content.Entity] = new() { + AdditionalData = new() { + [MadsIgnoreMetadataContent.EventId] = new MadsIgnoreMetadataContent { + WasUserAdded = false, + Policies = [policyEventReference] + } + } + }; + } + } + + foreach (var (previousEvent, newEvent) in updates.RemovedPolicies) { + if (previousEvent.Type != UserPolicyRuleEventContent.EventId) continue; + var previousContent = previousEvent.ContentAs<UserPolicyRuleEventContent>(); + + if (previousContent.Entity is null || previousContent.IsGlobRule()) continue; + if (previousContent.GetNormalizedRecommendation() != "m.ban") continue; + + var ignoreList = await homeserver.GetIgnoredUserListAsync(); + if (ignoreList.IgnoredUsers.TryGetValue(previousContent.Entity, out var existingRule)) { + if (existingRule.AdditionalData?.ContainsKey(MadsIgnoreMetadataContent.EventId) ?? false) { + var existingMetadata = existingRule.GetAdditionalData<MadsIgnoreMetadataContent>(MadsIgnoreMetadataContent.EventId); + existingMetadata.Policies.RemoveAll(x => x.Type == previousEvent.Type && x.RoomId == previousEvent.RoomId && x.StateKey == previousEvent.StateKey); + if (!existingMetadata.WasUserAdded) + ignoreList.IgnoredUsers.Remove(previousContent.Entity); + } + } + } + + await homeserver.SetAccountDataAsync(IgnoredUserListEventContent.EventId, ignoreListContent); + } + +#endregion + +#region Feature: Reject invites + private Task CheckPoliciesAgainstInvite(RoomInviteContext invite) { logger.LogInformation("Checking policies against invite"); var sw = Stopwatch.StartNew(); @@ -44,9 +121,9 @@ public class PolicyExecutor( return Task.CompletedTask; } - private async Task CheckPolicyAgainstOutstandingInvites(PolicyRuleEventContent policy) { + private async Task CheckPolicyAgainstOutstandingInvites(StateEventResponse newEvent) { var tasks = roomInviteHandler.Invites - .Select(invite => CheckPolicyAgainstInvite(invite, policy)) + .Select(invite => CheckPolicyAgainstInvite(invite, newEvent)) .Where(x => x is not null) .Cast<Task>() // from Task? .ToList(); @@ -54,7 +131,8 @@ public class PolicyExecutor( await Task.WhenAll(tasks); } - private Task? CheckPolicyAgainstInvite(RoomInviteContext invite, PolicyRuleEventContent policy) { + private Task? CheckPolicyAgainstInvite(RoomInviteContext invite, StateEventResponse policyEvent) { + var policy = policyEvent.TypedContent as PolicyRuleEventContent ?? throw new InvalidOperationException("Policy is null"); if (policy.Recommendation != "m.ban") return null; var policyMatches = false; @@ -91,4 +169,6 @@ public class PolicyExecutor( } }); } + +#endregion } \ No newline at end of file