Handle participants and chat rooms
This commit is contained in:
@@ -10,6 +10,7 @@ import ac.cord.auxiliary.compose.database.model.Mention
|
||||
import ac.cord.auxiliary.compose.database.model.NegentropySynchronizeRequest
|
||||
import ac.cord.auxiliary.compose.database.model.NostrEvent
|
||||
import ac.cord.auxiliary.compose.database.model.NostrEventRelay
|
||||
import ac.cord.auxiliary.compose.database.model.Participant
|
||||
import ac.cord.auxiliary.compose.database.model.Post
|
||||
import ac.cord.auxiliary.compose.database.model.Profile
|
||||
import ac.cord.auxiliary.compose.database.model.UnsignedNostrEvent
|
||||
@@ -24,7 +25,6 @@ import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
||||
import fr.acinq.bitcoin.crypto.musig2.Musig2
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Instant
|
||||
|
||||
@@ -352,14 +352,10 @@ abstract class NostrDao(
|
||||
giftWrapPayload
|
||||
)
|
||||
|
||||
val receiverPublicKeys = giftWrapPayload.receiverPublicKeys()
|
||||
logger.d("receiverPublicKeys: $receiverPublicKeys")
|
||||
|
||||
if (receiverPublicKeys.isNotEmpty()) {
|
||||
val chatRoomId = Musig2.aggregateKeys(
|
||||
giftWrapPayload.receiverPublicKeys()
|
||||
).value.toHex()
|
||||
// Process chatMessage and chatRoom stuff...
|
||||
val musig2AggregatedPublicKey = giftWrapPayload.aggregateParticipantsPublicKeys()
|
||||
if (musig2AggregatedPublicKey != null) {
|
||||
val chatRoomId = musig2AggregatedPublicKey.value.toHex()
|
||||
logger.d("ChatRoomId: $chatRoomId")
|
||||
// Find or create chatRoom
|
||||
val localChatRoom = database.chatRoomDao().findChatRoomById(
|
||||
chatRoomId
|
||||
@@ -375,11 +371,27 @@ abstract class NostrDao(
|
||||
initialGiftWrapUnsignedId = giftWrapPayload.id
|
||||
)
|
||||
)
|
||||
|
||||
// Add participants...
|
||||
database.participantDao().upsert(
|
||||
giftWrapPayload.receiverPubKeys().map {
|
||||
Participant(
|
||||
participantPublicKey = it,
|
||||
chatRoomId = chatRoomId
|
||||
)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
// TODO: Update subject from tags...
|
||||
giftWrapPayload.parseSubject()?.let { subject ->
|
||||
database.chatRoomDao().upsert(
|
||||
localChatRoom.chatRoom.copy(
|
||||
subject = subject,
|
||||
updatedAt = giftWrapPayload.createdAt
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Save chatMessage
|
||||
database.chatMessageDao().upsert(
|
||||
ChatMessage(
|
||||
giftWrapPayloadId = giftWrapPayload.id,
|
||||
@@ -390,8 +402,9 @@ abstract class NostrDao(
|
||||
content = giftWrapPayload.content,
|
||||
)
|
||||
)
|
||||
} else {
|
||||
logger.w("Failed to setup chatRoom for message")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,15 @@ import ac.cord.auxiliary.compose.database.model.traits.UserViewableEntity
|
||||
import androidx.room3.Entity
|
||||
import androidx.room3.ForeignKey
|
||||
import androidx.room3.PrimaryKey
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Kind
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
||||
import com.vitorpamplona.quartz.nip14Subject.subject
|
||||
import fr.acinq.bitcoin.PublicKey
|
||||
import fr.acinq.bitcoin.XonlyPublicKey
|
||||
import fr.acinq.bitcoin.crypto.musig2.Musig2
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Instant
|
||||
|
||||
@@ -73,17 +78,45 @@ data class GiftWrapPayload( // TODO: Rename this to GiftWrapPayload...
|
||||
override val viewedAt: Instant? = null,
|
||||
override val deletedAt: Instant? = null, // Who this message should be seen by (used to derive conversationId)
|
||||
): TimestampedEntity, LocalStoreEntity, UserViewableEntity, SoftDeletableEntity {
|
||||
val logger = Logger.withTag(TAG)
|
||||
|
||||
fun receiverPublicKeys(): List<PublicKey> = try {
|
||||
tags.taggedUsers().map {
|
||||
fun aggregateParticipantsPublicKeys(): XonlyPublicKey? = try {
|
||||
logger.d("aggregateParticipantsPublicKeys")
|
||||
val hexKeys = tags.taggedUsers().map {
|
||||
it.pubKey
|
||||
}
|
||||
|
||||
logger.d("HexKeys: $hexKeys")
|
||||
val publicKeys = hexKeys.map {
|
||||
PublicKey(
|
||||
it.pubKey.hexToByteArray()
|
||||
PublicKey.compress(it.hexToByteArray())
|
||||
)
|
||||
}
|
||||
logger.d("PublicKeys: $publicKeys")
|
||||
|
||||
val chatRoomXOnlyPublicKey = Musig2.aggregateKeys(
|
||||
publicKeys
|
||||
)
|
||||
logger.d("ChatRoomXOnly: $chatRoomXOnlyPublicKey")
|
||||
|
||||
return chatRoomXOnlyPublicKey
|
||||
} catch (e: Throwable) {
|
||||
logger.e("Failed to aggregate participants publicKeys", e)
|
||||
return null
|
||||
}
|
||||
|
||||
fun receiverPubKeys(): List<HexKey> = try {
|
||||
tags.taggedUsers().map {
|
||||
it.pubKey
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
fun parseSubject(): String? {
|
||||
return tags.subject()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || this::class != other::class) return false
|
||||
@@ -121,4 +154,8 @@ data class GiftWrapPayload( // TODO: Rename this to GiftWrapPayload...
|
||||
result = 31 * result + (deletedAt?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "GiftWrapPayload"
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,7 @@ class NavigationViewModel(
|
||||
|
||||
init {
|
||||
observeUnsignedNostrEvents()
|
||||
// TODO: observePendingUnsignedChatMessages
|
||||
observePendingBroadcastNostrEventRequests()
|
||||
observeProfile()
|
||||
observePendingSyncNostrEventRequests()
|
||||
|
||||
Reference in New Issue
Block a user