From 60b92a0940e2072fefbe903e646ded78bc9768e2 Mon Sep 17 00:00:00 2001 From: Rory& Date: Sat, 10 May 2025 08:26:20 +0200 Subject: Recover from invalid ignore list entries --- LibMatrix | 2 +- MatrixAntiDmSpam.Core/PolicyExecutor.cs | 71 +++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/LibMatrix b/LibMatrix index 51ff4a3..a2b318f 160000 --- a/LibMatrix +++ b/LibMatrix @@ -1 +1 @@ -Subproject commit 51ff4a3b95ab38dd46c88f4e5482bf78449bb88c +Subproject commit a2b318f6f52dfec7f217643273e5b4e0855fe9e0 diff --git a/MatrixAntiDmSpam.Core/PolicyExecutor.cs b/MatrixAntiDmSpam.Core/PolicyExecutor.cs index 40432b8..8a24995 100644 --- a/MatrixAntiDmSpam.Core/PolicyExecutor.cs +++ b/MatrixAntiDmSpam.Core/PolicyExecutor.cs @@ -27,18 +27,7 @@ public class PolicyExecutor( roomInviteHandler.OnInviteReceived.Add(CheckPoliciesAgainstInvite); policyStore.OnPolicyAdded.Add(CheckPolicyAgainstOutstandingInvites); if (config.IgnoreBannedUsers) { - var ignoreList = await homeserver.GetAccountDataOrNullAsync(IgnoredUserListEventContent.EventId); - if (ignoreList != null) { - ignoreList.IgnoredUsers.RemoveAll((id, meta) => { - if (meta.AdditionalData?.ContainsKey(MadsIgnoreMetadataContent.EventId) ?? false) { - var metadata = meta.GetAdditionalData(MadsIgnoreMetadataContent.EventId); - if (metadata?["was_user_added"]?.GetValue() ?? false) { - return true; - } - } - return false; - }); - } + await CleanupInvalidIgnoreListEntries(); policyStore.OnPoliciesChanged.Add(UpdateIgnoreList); } } @@ -52,7 +41,7 @@ public class PolicyExecutor( List<(StateEventResponse Old, StateEventResponse New)> UpdatedPolicies, List<(StateEventResponse Old, StateEventResponse New)> RemovedPolicies) updates ) { - var ignoreListContent = await homeserver.GetIgnoredUserListAsync(); + var ignoreListContent = await FilterInvalidIgnoreListEntries(); foreach (var newEvent in updates.NewPolicies) { var content = newEvent.TypedContent as PolicyRuleEventContent; @@ -110,17 +99,64 @@ public class PolicyExecutor( await homeserver.SetAccountDataAsync(IgnoredUserListEventContent.EventId, ignoreListContent); } + + private async Task FilterInvalidIgnoreListEntries() { + var ignoreList = await homeserver.GetAccountDataOrNullAsync(IgnoredUserListEventContent.EventId); + if (ignoreList != null) { + ignoreList.IgnoredUsers.RemoveAll((id, ignoredUserData) => { + if (ignoredUserData.AdditionalData is null) return false; + if (!ignoredUserData.AdditionalData.ContainsKey(MadsIgnoreMetadataContent.EventId)) return false; + var metadata = ignoredUserData.GetAdditionalData(MadsIgnoreMetadataContent.EventId)!; + + if (metadata.ContainsKey("policies")) { + var policies = metadata["policies"]!.AsArray(); + + bool IsPolicyEntryValid(JsonNode? p) => + p!["room_id"]?.GetValue() != null && p["type"]?.GetValue() != null && p["state_key"]?.GetValue() != null; + + if (policies.Any(x => !IsPolicyEntryValid(x))) { + logger.LogWarning("Found invalid policy reference in ignore list, removing! {policy}", + policies.Where(x => !IsPolicyEntryValid(x)).Select(x => x.ToJson(ignoreNull: true))); + metadata["policies"] = new JsonArray(policies.Where(IsPolicyEntryValid).ToArray()); + } + } + + return metadata["was_user_added"]?.GetValue() is null or false; + }); + } - private async Task TryRecoverIgnoreList(IgnoredUserListEventContent content) { + return ignoreList; + } + + private async Task CleanupInvalidIgnoreListEntries() { + var ignoreList = await FilterInvalidIgnoreListEntries(); + ignoreList.IgnoredUsers.RemoveAll((id, _) => !(id.StartsWith('@') && id.Contains(':'))); + List idsToRemove = []; + foreach (var (id, ignoredUserData) in ignoreList.IgnoredUsers) { + if (ignoredUserData.AdditionalData is null) continue; + if (!ignoredUserData.AdditionalData.ContainsKey(MadsIgnoreMetadataContent.EventId)) continue; + try { + var metadata = ignoredUserData.GetAdditionalData(MadsIgnoreMetadataContent.EventId)!; + + if (metadata.Policies.Count == 0 && !metadata.WasUserAdded) { + idsToRemove.Add(id); + } + } + catch (Exception e) { + logger.LogError(e, "Failed to parse ignore list entry for {}", id); + } + } + foreach (var id in idsToRemove) { + ignoreList.IgnoredUsers.Remove(id); + } + await homeserver.SetAccountDataAsync(IgnoredUserListEventContent.EventId, ignoreList); } #endregion #region Feature: Report blocked invites - - #endregion #region Feature: Reject invites @@ -172,7 +208,8 @@ public class PolicyExecutor( } if (!policyMatches) return null; - logger.LogWarning("[{}] Rejecting invite to {}, matching {} {}", homeserver.WhoAmI.UserId, invite.RoomId, policy.GetType().GetFriendlyName(), policy.ToJson(ignoreNull: true)); + logger.LogWarning("[{}] Rejecting invite to {}, matching {} {}", homeserver.WhoAmI.UserId, invite.RoomId, policy.GetType().GetFriendlyName(), + policy.ToJson(ignoreNull: true)); return Task.Run(async () => { if (_logRoom is not null) { -- cgit 1.5.1