From 3a43c4f7bb7546fe40f8af541a5625a5f9acfe87 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 3 Jun 2026 13:30:52 +0000 Subject: [PATCH] fix: register CommunityRulesEvent in EventFactory Kind 34551 (CommunityRulesEvent) was missing from EventFactory.create, so signing a community-rules template produced a generic Event. Returning it as CommunityRulesEvent in Account.sendCommunityRules threw a ClassCastException when publishing community rules. Register the kind in the factory and add a regression test. --- .../quartz/utils/EventFactory.kt | 2 + .../rules/CommunityRulesEventFactoryTest.kt | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/rules/CommunityRulesEventFactoryTest.kt diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt index bc81ff54a3..5ae5eed355 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt @@ -217,6 +217,7 @@ import com.vitorpamplona.quartz.nip71Video.VideoVerticalEvent import com.vitorpamplona.quartz.nip72ModCommunities.approval.CommunityPostApprovalEvent import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent +import com.vitorpamplona.quartz.nip72ModCommunities.rules.CommunityRulesEvent import com.vitorpamplona.quartz.nip75ZapGoals.GoalEvent import com.vitorpamplona.quartz.nip78AppData.AppDataEvent import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent @@ -400,6 +401,7 @@ class EventFactory { CommunityDefinitionEvent.KIND -> CommunityDefinitionEvent(id, pubKey, createdAt, tags, content, sig) CommunityListEvent.KIND -> CommunityListEvent(id, pubKey, createdAt, tags, content, sig) CommunityPostApprovalEvent.KIND -> CommunityPostApprovalEvent(id, pubKey, createdAt, tags, content, sig) + CommunityRulesEvent.KIND -> CommunityRulesEvent(id, pubKey, createdAt, tags, content, sig) ContactListEvent.KIND -> ContactListEvent(id, pubKey, createdAt, tags, content, sig) DeletionEvent.KIND -> DeletionEvent(id, pubKey, createdAt, tags, content, sig) DraftWrapEvent.KIND -> DraftWrapEvent(id, pubKey, createdAt, tags, content, sig) diff --git a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/rules/CommunityRulesEventFactoryTest.kt b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/rules/CommunityRulesEventFactoryTest.kt new file mode 100644 index 0000000000..da284344c4 --- /dev/null +++ b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/rules/CommunityRulesEventFactoryTest.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nip72ModCommunities.rules + +import com.vitorpamplona.quartz.nip01Core.core.Event +import com.vitorpamplona.quartz.utils.EventFactory +import kotlin.test.Test +import kotlin.test.assertTrue + +class CommunityRulesEventFactoryTest { + /** + * Regression test for the ClassCastException seen in production when + * publishing community rules: the factory used to fall back to the generic + * [Event] for kind 34551 because [CommunityRulesEvent] was never registered, + * so `signer.sign(...)` produced an [Event] that couldn't be cast back to + * [CommunityRulesEvent] in `Account.sendCommunityRules`. + */ + @Test + fun factoryBuildsCommunityRulesEventForKind34551() { + val event: Event = + EventFactory.create( + id = "00".repeat(32), + pubKey = "11".repeat(32), + createdAt = 1_700_000_000L, + kind = CommunityRulesEvent.KIND, + tags = arrayOf(arrayOf("d", "my-community")), + content = "", + sig = "22".repeat(64), + ) + + assertTrue( + event is CommunityRulesEvent, + "Expected a CommunityRulesEvent but got ${event::class.simpleName}", + ) + } +}