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