diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/NostrDao.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/NostrDao.kt index 9f6f6cea..d9a0ce93 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/NostrDao.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/NostrDao.kt @@ -341,6 +341,8 @@ abstract class NostrDao( userPublicKey = activeKeyPair.pubKey.toHex() )?.let { groupEvent -> + logger.d("groupEvent: $groupEvent") + groupEvent.groupId()?.let { chatRoomId -> val localChatRoom = database.chatRoomDao().findChatRoomById(chatRoomId) @@ -365,19 +367,26 @@ abstract class NostrDao( if (memberPubkeys.contains(activeKeyPair.pubKey.toHex())) { // Ingest message... - val groupEventResult = MarmotInboundManager.processGroupEvent( + MarmotInboundManager.processGroupEvent( database = database, activeKeyPair = activeKeyPair, localChatRoom = localChatRoom, mlsGroup = mlsGroup, groupEvent = groupEvent - )?.let { chatMessage -> - database.chatMessageDao().upsert( - chatMessage - ) - } + )?.let { groupEventResult -> - // Save groupEventResult as chatMessage... + ChatMessage.fromGroupEventResult( + activeKeyPair = activeKeyPair, + groupEvent = groupEvent, + groupEventResult = groupEventResult, + )?.let { chatMessage -> + database.chatMessageDao().upsert( + chatMessage + ) + } + + // TODO: Process none chatMessages... + } } else { diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/ChatMessage.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/ChatMessage.kt index 399466b8..48eb5294 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/ChatMessage.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/ChatMessage.kt @@ -7,11 +7,15 @@ import at.torch.compose.database.model.traits.LocalStoreEntity import at.torch.compose.database.model.traits.SoftDeletableEntity import at.torch.compose.database.model.traits.TimestampedEntity import at.torch.compose.database.model.traits.UserViewableEntity +import at.torch.compose.exceptions.GiftWrapImpersonationException import at.torch.compose.extensions.toHex import com.vitorpamplona.quartz.marmot.GroupEventResult import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent +import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair +import com.vitorpamplona.quartz.nip17Dm.messages.ChatMessageEvent +import com.vitorpamplona.quartz.nipC7Chats.ChatEvent import kotlin.time.Clock import kotlin.time.Instant @@ -63,16 +67,38 @@ data class ChatMessage( ): ChatMessage? { return when(groupEventResult) { is GroupEventResult.ApplicationMessage -> { - ChatMessage( - giftWrapPayloadId = null, - messageType = "message", - groupEventId = groupEvent.id, - senderPublicKey = groupEvent.pubKey, - isUserMessage = activeKeyPair.pubKey.toHex() == groupEvent.pubKey, - chatRoomId = groupEventResult.groupId, - createdAt = Instant.fromEpochSeconds(groupEvent.createdAt), - content = groupEventResult.innerEventJson, // TODO: Figure out what to do here... - ) + val event = Event.fromJsonOrNull(groupEventResult.innerEventJson) + + if (event?.pubKey != groupEvent.pubKey) { + throw GiftWrapImpersonationException("" + + "The innerEvent pubkey (${event?.pubKey}) doesn't match the groupEvent pubkey ${groupEvent.pubKey}") + } + when (event.kind) { + ChatEvent.KIND -> { + ChatMessage( + giftWrapPayloadId = null, + messageType = "message", + groupEventId = groupEvent.id, + senderPublicKey = event.pubKey, + isUserMessage = activeKeyPair.pubKey.toHex() == groupEvent.pubKey, + chatRoomId = groupEventResult.groupId, + createdAt = Instant.fromEpochSeconds(event.createdAt), + content = event.content, // TODO: Figure out what to do here... + ) + } + else -> { + ChatMessage( + giftWrapPayloadId = null, + messageType = "unsupported", + groupEventId = groupEvent.id, + senderPublicKey = groupEvent.pubKey, + isUserMessage = activeKeyPair.pubKey.toHex() == groupEvent.pubKey, + chatRoomId = groupEventResult.groupId, + createdAt = Instant.fromEpochSeconds(groupEvent.createdAt), + content = groupEventResult.innerEventJson, // TODO: Figure out what to do here... + ) + } + } } is GroupEventResult.CommitPending -> { ChatMessage( diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/managers/MarmotInboundManager.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/managers/MarmotInboundManager.kt index 774be6cd..80287635 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/managers/MarmotInboundManager.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/managers/MarmotInboundManager.kt @@ -57,9 +57,9 @@ object MarmotInboundManager { localChatRoom: LocalChatRoom, mlsGroup: MlsGroup, groupEvent: GroupEvent - ): ChatMessage? { + ): GroupEventResult? { groupEvent.groupId()?.let { groupId -> - val result = try { + return try { val mlsBytes = tryDecryptOuterLayer( mlsGroup, groupEvent.encryptedContent() @@ -105,12 +105,6 @@ object MarmotInboundManager { } catch (e: Throwable) { GroupEventResult.Error(groupId, "Failed to process GroupEvent: ${e.message}") } - - return ChatMessage.fromGroupEventResult( - activeKeyPair = activeKeyPair, - groupEvent = groupEvent, - groupEventResult = result, - ) } return null