Use unique constraint when saving to the database.
This commit is contained in:
@@ -1,18 +1,23 @@
|
||||
package at.torch.compose.database.dao
|
||||
|
||||
import androidx.room3.Dao
|
||||
import androidx.room3.Insert
|
||||
import androidx.room3.Query
|
||||
import androidx.room3.Upsert
|
||||
import at.torch.compose.database.model.GiftWrapPayload
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface GiftWrapPayloadDao {
|
||||
@Query("SELECT * FROM GiftWrapPayload")
|
||||
fun getAllGiftWrapUnsigned(): List<at.torch.compose.database.model.GiftWrapPayload>
|
||||
fun getAllGiftWrapUnsigned(): List<GiftWrapPayload>
|
||||
|
||||
@Query("SELECT * FROM GiftWrapPayload WHERE publicKey = :publicKey AND giftWrapSealId IS NULL")
|
||||
fun observeUnsealedGiftWrapPayloads(publicKey: String): Flow<at.torch.compose.database.model.GiftWrapPayload?>
|
||||
fun observeUnsealedGiftWrapPayloads(publicKey: String): Flow<GiftWrapPayload?>
|
||||
|
||||
@Upsert
|
||||
suspend fun upsert(giftWrapPayload: at.torch.compose.database.model.GiftWrapPayload)
|
||||
suspend fun upsert(giftWrapPayload: GiftWrapPayload)
|
||||
|
||||
@Insert
|
||||
suspend fun insert(giftWrapPayload: GiftWrapPayload)
|
||||
}
|
||||
@@ -45,6 +45,7 @@ import com.vitorpamplona.quartz.nip59Giftwrap.rumors.RumorAssembler
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlin.io.encoding.Base64
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Instant
|
||||
|
||||
@Dao
|
||||
@@ -121,7 +122,7 @@ abstract class MarmotOutboundDao(
|
||||
}
|
||||
|
||||
@Transaction
|
||||
open suspend fun inviteMember(
|
||||
open suspend fun inviteMemberToChatRoom(
|
||||
localChatRoom: LocalChatRoom,
|
||||
peerPublicKey: HexKey,
|
||||
peerKeyPackage: MarmotKeyPackage,
|
||||
@@ -204,6 +205,7 @@ abstract class MarmotOutboundDao(
|
||||
welcomeBytes = welcomeBytes,
|
||||
peerKeyPackageEventId = peerKeyPackage.id,
|
||||
relays = relays,
|
||||
createdAt = Clock.System.now()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -283,51 +285,64 @@ abstract class MarmotOutboundDao(
|
||||
welcomeBytes: ByteArray,
|
||||
peerKeyPackageEventId: HexKey,
|
||||
relays: List<String>,
|
||||
createdAt: Instant
|
||||
) {
|
||||
val welcomeBase64 = Base64.encode(
|
||||
source = welcomeBytes
|
||||
)
|
||||
try {
|
||||
val welcomeBase64 = Base64.encode(
|
||||
source = welcomeBytes
|
||||
)
|
||||
|
||||
// GiftWrap...
|
||||
val welcomeEvent = WelcomeEvent.build(
|
||||
welcomeBase64 = welcomeBase64,
|
||||
keyPackageEventId = peerKeyPackageEventId,
|
||||
relays = relays.map { NormalizedRelayUrl(it) },
|
||||
nostrGroupId = nostrGroupId,
|
||||
)
|
||||
// Compute welcomeEventId
|
||||
val welcomeEventId = EventHasher.hashId(
|
||||
pubKey = userPublicKey,
|
||||
kind = welcomeEvent.kind,
|
||||
tags = welcomeEvent.tags,
|
||||
createdAt = welcomeEvent.createdAt,
|
||||
content = welcomeEvent.content
|
||||
)
|
||||
|
||||
database.giftWrapPayloadDao().upsert(
|
||||
GiftWrapPayload(
|
||||
id = welcomeEventId,
|
||||
publicKey = userPublicKey,
|
||||
chatRoomId = nostrGroupId,
|
||||
// GiftWrap...
|
||||
val welcomeEvent = WelcomeEvent.build(
|
||||
welcomeBase64 = welcomeBase64,
|
||||
createdAt = createdAt.epochSeconds,
|
||||
keyPackageEventId = peerKeyPackageEventId,
|
||||
relays = relays.map { NormalizedRelayUrl(it) },
|
||||
nostrGroupId = nostrGroupId,
|
||||
)
|
||||
// Compute welcomeEventId
|
||||
val welcomeEventId = EventHasher.hashId(
|
||||
pubKey = userPublicKey,
|
||||
kind = welcomeEvent.kind,
|
||||
tags = welcomeEvent.tags,
|
||||
content = welcomeEvent.content,
|
||||
createdAt = Instant.fromEpochSeconds(welcomeEvent.createdAt)
|
||||
createdAt = welcomeEvent.createdAt,
|
||||
content = welcomeEvent.content
|
||||
)
|
||||
)
|
||||
logger.d("Welcome Event: ${welcomeEvent.toJson()}")
|
||||
logger.d("Welcome Event Id: $welcomeEventId")
|
||||
|
||||
// Save chatMessage for the invite...
|
||||
database.chatMessageDao().upsert(
|
||||
ChatMessage(
|
||||
content = "Invited participant to chat", // use profile.humanReadable...
|
||||
chatRoomId = nostrGroupId,
|
||||
senderPublicKey = userPublicKey,
|
||||
isUserMessage = true, // TODO: This is information message...
|
||||
giftWrapPayloadId = welcomeEventId,
|
||||
marmotGroupEventId = null,
|
||||
marmotInnerEventId = null
|
||||
|
||||
database.giftWrapPayloadDao().insert(
|
||||
GiftWrapPayload(
|
||||
id = welcomeEventId,
|
||||
publicKey = userPublicKey,
|
||||
chatRoomId = nostrGroupId,
|
||||
kind = welcomeEvent.kind,
|
||||
tags = welcomeEvent.tags,
|
||||
content = welcomeEvent.content,
|
||||
createdAt = Instant.fromEpochSeconds(welcomeEvent.createdAt)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
database.marmotKeyPackageDao().getMarmotKeyPackageById(peerKeyPackageEventId)?.let { marmotKeyPackage ->
|
||||
database.profileDao().getProfileByPublicKey(marmotKeyPackage.publicKey)?.let { profile ->
|
||||
// Save chatMessage for the invite...
|
||||
database.chatMessageDao().upsert(
|
||||
ChatMessage(
|
||||
content = "Invited ${profile.humanReadableNameOrPubkey() ?: "participant"} to chat", // use profile.humanReadable...
|
||||
chatRoomId = nostrGroupId,
|
||||
senderPublicKey = userPublicKey,
|
||||
isUserMessage = true, // TODO: This is information message...
|
||||
giftWrapPayloadId = welcomeEventId,
|
||||
marmotGroupEventId = null,
|
||||
marmotInnerEventId = null
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
logger.e("Failed to deliver welcome:", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun encryptedCommitEvent(
|
||||
|
||||
@@ -136,7 +136,7 @@ class DatabaseChatRepository(
|
||||
peerPublicKey: HexKey,
|
||||
peerKeyPackage: MarmotKeyPackage
|
||||
) {
|
||||
database.marmotOutboundDao().inviteMember(
|
||||
database.marmotOutboundDao().inviteMemberToChatRoom(
|
||||
localChatRoom = localChatRoom,
|
||||
peerPublicKey = peerPublicKey,
|
||||
peerKeyPackage = peerKeyPackage
|
||||
|
||||
@@ -7,6 +7,7 @@ import at.torch.compose.database.model.UnsignedNostrEvent
|
||||
import at.torch.compose.database.model.intermdiate.LocalAccount
|
||||
import at.torch.compose.database.model.intermdiate.LocalBroadcastNostrEventRequest
|
||||
import at.torch.compose.database.model.types.SynchronizationFilter
|
||||
import at.torch.compose.extensions.toHex
|
||||
import at.torch.compose.nostr.Relays
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageRelayListEvent
|
||||
@@ -406,15 +407,20 @@ class DatabaseNostrRepository(
|
||||
database.marmotCommitResultDao().getMarmotCommitRequestById(
|
||||
nostrEventId = broadcastNostrEventRequest.nostrEventId
|
||||
)?.let { marmotCommitResult ->
|
||||
logger.d("marmotCommitResult: $marmotCommitResult")
|
||||
if (marmotCommitResult.isOneMemberInitialGroupCreation.not()) {
|
||||
logger.d("Deliver Welcome")
|
||||
database.chatRoomDao().findChatRoomById(marmotCommitResult.chatRoomId)?.let { localChatRoom ->
|
||||
// TODO: Update status of participant Invitation.PENDING -> Invitation.SENT
|
||||
logger.d("localChatRoom: $localChatRoom")
|
||||
marmotCommitResult.welcomeBytes?.let { welcomeBytes ->
|
||||
logger.d("welcomeBytes: ${welcomeBytes.toHex()}")
|
||||
database.marmotOutboundDao().deliveryWelcome(
|
||||
nostrGroupId = marmotCommitResult.chatRoomId,
|
||||
userPublicKey = marmotCommitResult.userPublicKey,
|
||||
welcomeBytes = welcomeBytes,
|
||||
peerKeyPackageEventId = marmotCommitResult.peerKeyPackageEventId,
|
||||
createdAt = marmotCommitResult.createdAt,
|
||||
relays = Relays.DefaultDMRelayList.map { it.url } // TODO: Get localChatRoom relays...
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user