Simplifying the refactoring of the DecryptAndIndexProcessor

This commit is contained in:
Vitor Pamplona
2025-08-05 15:04:23 -04:00
parent 4675212e1d
commit 63f62167a4
5 changed files with 140 additions and 244 deletions

View File

@@ -24,6 +24,7 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
import com.vitorpamplona.quartz.utils.LargeCache import com.vitorpamplona.quartz.utils.LargeCache
import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.persistentSetOf
@@ -42,6 +43,26 @@ class ChatroomList(
fun getOrCreatePrivateChatroom(key: ChatroomKey): Chatroom = getOrCreatePrivateChatroomSync(key) fun getOrCreatePrivateChatroom(key: ChatroomKey): Chatroom = getOrCreatePrivateChatroomSync(key)
fun add(
event: ChatroomKeyable,
msg: Note,
) {
if (event.isIncluded(ownerPubKey)) {
val key = event.chatroomKey(ownerPubKey)
addMessage(key, msg)
}
}
fun delete(
event: ChatroomKeyable,
msg: Note,
) {
if (event.isIncluded(ownerPubKey)) {
val key = event.chatroomKey(ownerPubKey)
removeMessage(key, msg)
}
}
fun addMessage( fun addMessage(
room: ChatroomKey, room: ChatroomKey,
msg: Note, msg: Note,
@@ -49,6 +70,9 @@ class ChatroomList(
val privateChatroom = getOrCreatePrivateChatroom(room) val privateChatroom = getOrCreatePrivateChatroom(room)
if (msg !in privateChatroom.messages) { if (msg !in privateChatroom.messages) {
privateChatroom.addMessageSync(msg) privateChatroom.addMessageSync(msg)
if (msg.author?.pubkeyHex == ownerPubKey) {
privateChatroom.ownerSentMessage = true
}
} }
} }

View File

@@ -25,42 +25,64 @@ import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.privateChats.ChatroomList
import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.IEvent
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEvent
import com.vitorpamplona.quartz.nip17Dm.messages.ChatMessageEvent
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
import com.vitorpamplona.quartz.nip57Zaps.PrivateZapCache
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlin.reflect.KClass
class EventProcessor( class EventProcessor(
private val account: Account, private val account: Account,
private val cache: LocalCache, private val cache: LocalCache,
) { ) {
private val decryptionService = DecryptionService(account)
private val indexingService = IndexingService(account, cache) private val indexingService = IndexingService(account, cache)
private val chatroomService = ChatroomService(account)
private val eventHandlers = createEventHandlers() private val chatHandler = ChatHandler(account.chatroomList)
private val otsHandler = OtsEventHandler(account)
private val draftHandler = DraftEventHandler(account, indexingService)
private val giftWrapHandler = GiftWrapEventHandler(account, cache, this)
private val sealHandler = SealedRumorEventHandler(account, cache, this)
private val zapRequest = LnZapRequestEventHandler(account.privateZapsDecryptionCache)
private val zapEvent = LnZapEventHandler(account.privateZapsDecryptionCache)
suspend fun consume(note: Note) { suspend fun consume(note: Note) {
note.event?.let { event -> note.event?.let { event ->
try { try {
processEvent(event, note, note) consumeEvent(event, note, note)
} catch (e: Exception) { } catch (e: Exception) {
Log.e("EventProcessor", "Error processing note", e) Log.e("EventProcessor", "Error processing note", e)
} }
} }
} }
internal suspend fun consumeEvent(
event: Event,
eventNote: Note,
publicNote: Note,
) {
when (event) {
is ChatroomKeyable -> chatHandler.add(event, eventNote, publicNote)
is OtsEvent -> otsHandler.add(event, eventNote, publicNote)
is DraftEvent -> draftHandler.add(event, eventNote, publicNote)
is GiftWrapEvent -> giftWrapHandler.add(event, eventNote, publicNote)
is SealedRumorEvent -> sealHandler.add(event, eventNote, publicNote)
is LnZapRequestEvent -> zapRequest.add(event, eventNote, publicNote)
}
}
suspend fun delete(note: Note) { suspend fun delete(note: Note) {
note.event?.let { event -> note.event?.let { event ->
try { try {
@@ -71,33 +93,20 @@ class EventProcessor(
} }
} }
internal suspend fun processEvent(
event: Event,
eventNote: Note,
publicNote: Note,
) {
eventHandlers[event::class]?.process(event, eventNote, publicNote)
}
internal suspend fun deleteEvent( internal suspend fun deleteEvent(
event: Event, event: Event,
eventNote: Note, note: Note,
) { ) {
eventHandlers[event::class]?.delete(event, eventNote) when (event) {
is ChatroomKeyable -> chatHandler.delete(event, note)
is OtsEvent -> otsHandler.delete(event, note)
is DraftEvent -> draftHandler.delete(event, note)
is GiftWrapEvent -> giftWrapHandler.delete(event, note)
is SealedRumorEvent -> sealHandler.delete(event, note)
is LnZapRequestEvent -> zapRequest.delete(event, note)
is LnZapEvent -> zapEvent.delete(event, note)
}
} }
private fun createEventHandlers(): Map<KClass<out Event>, EventHandler> =
mapOf(
PrivateDmEvent::class to PrivateDmHandler(chatroomService),
ChatMessageEvent::class to ChatMessageHandler(chatroomService),
ChatMessageEncryptedFileHeaderEvent::class to ChatMessageEncryptedFileHeaderHandler(chatroomService),
OtsEvent::class to OtsEventHandler(account),
DraftEvent::class to DraftEventHandler(decryptionService, indexingService),
GiftWrapEvent::class to GiftWrapEventHandler(decryptionService, cache, this),
SealedRumorEvent::class to SealedRumorEventHandler(decryptionService, cache, this),
LnZapRequestEvent::class to LnZapRequestEventHandler(decryptionService),
LnZapEvent::class to LnZapEventHandler(decryptionService),
)
suspend fun runNew(newNotes: Set<Note>) { suspend fun runNew(newNotes: Set<Note>) {
try { try {
@@ -122,7 +131,14 @@ class EventProcessor(
val deletedDrafts = val deletedDrafts =
newNotes.mapNotNull { note -> newNotes.mapNotNull { note ->
val event = note.event val event = note.event
if (event is DraftEvent && event.isDeleted()) note else null if (event is DraftEvent &&
event.isDeleted() &&
!cache.deletionIndex.hasBeenDeleted(event)
) {
note
} else {
null
}
} }
if (deletedDrafts.isNotEmpty()) { if (deletedDrafts.isNotEmpty()) {
@@ -132,38 +148,6 @@ class EventProcessor(
} }
} }
class DecryptionService(
val account: Account,
) {
suspend fun unwrapGiftWrap(event: GiftWrapEvent): Event? = event.unwrapOrNull(account.signer)
suspend fun unsealRumor(event: SealedRumorEvent): Event? = event.unsealOrNull(account.signer)
suspend fun decryptDraft(event: DraftEvent): Event? =
account.draftsDecryptionCache.preCachedDraft(event)
?: account.draftsDecryptionCache.cachedDraft(event)
suspend fun handlePrivateZap(event: LnZapRequestEvent) {
if (account.privateZapsDecryptionCache.cachedPrivateZap(event) == null && event.isPrivateZap()) {
account.privateZapsDecryptionCache.decryptPrivateZap(event)
}
}
fun deletePrivateZap(event: LnZapRequestEvent) {
if (event.isPrivateZap()) {
account.privateZapsDecryptionCache.delete(event)
}
}
fun deletePrivateZapFromZapEvent(event: LnZapEvent) {
event.zapRequest?.let { req ->
if (req.isPrivateZap()) {
account.privateZapsDecryptionCache.delete(req)
}
}
}
}
class IndexingService( class IndexingService(
private val account: Account, private val account: Account,
private val cache: LocalCache, private val cache: LocalCache,
@@ -171,44 +155,12 @@ class IndexingService(
fun indexDraftAsRealEvent( fun indexDraftAsRealEvent(
draftEventWrap: Note, draftEventWrap: Note,
rumor: Event, rumor: Event,
) {
setupReplyRelationships(draftEventWrap, rumor)
indexByEventType(draftEventWrap, rumor)
}
private fun setupReplyRelationships(
draftEventWrap: Note,
rumor: Event,
) { ) {
draftEventWrap.replyTo = cache.computeReplyTo(rumor) draftEventWrap.replyTo = cache.computeReplyTo(rumor)
draftEventWrap.replyTo?.forEach { it.addReply(draftEventWrap) } draftEventWrap.replyTo?.forEach { it.addReply(draftEventWrap) }
}
private fun indexByEventType(
draftEventWrap: Note,
rumor: Event,
) {
val chatroomService = ChatroomService(account)
when (rumor) { when (rumor) {
is PrivateDmEvent -> { is ChatroomKeyable -> account.chatroomList.add(rumor, draftEventWrap)
if (rumor.canDecrypt(account.signer)) {
val key = rumor.chatroomKey(account.signer.pubKey)
chatroomService.addMessage(key, draftEventWrap)
}
}
is ChatMessageEvent -> {
if (rumor.isIncluded(account.signer.pubKey)) {
val key = rumor.chatroomKey(account.signer.pubKey)
chatroomService.addMessage(key, draftEventWrap)
}
}
is ChatMessageEncryptedFileHeaderEvent -> {
if (rumor.isIncluded(account.signer.pubKey)) {
val key = rumor.chatroomKey(account.signer.pubKey)
chatroomService.addMessage(key, draftEventWrap)
}
}
is EphemeralChatEvent -> { is EphemeralChatEvent -> {
rumor.roomId()?.let { roomId -> rumor.roomId()?.let { roomId ->
val channel = cache.getOrCreateEphemeralChannel(roomId) val channel = cache.getOrCreateEphemeralChannel(roomId)
@@ -231,160 +183,77 @@ class IndexingService(
} }
} }
class ChatroomService( interface EventHandler<T : IEvent> {
val account: Account, suspend fun add(
) { event: T,
fun addMessage(
chatroomKey: ChatroomKey,
note: Note,
) {
account.chatroomList.addMessage(chatroomKey, note)
}
fun removeMessage(
chatroomKey: ChatroomKey,
note: Note,
) {
account.chatroomList.removeMessage(chatroomKey, note)
}
}
interface EventHandler {
suspend fun process(
event: Event,
eventNote: Note, eventNote: Note,
publicNote: Note, publicNote: Note,
) {} ) {}
suspend fun delete( suspend fun delete(
event: Event, event: T,
eventNote: Note, eventNote: Note,
) {} ) {}
} }
class PrivateDmHandler( class ChatHandler(
private val chatroomService: ChatroomService, private val chatroomList: ChatroomList,
) : EventHandler { ) : EventHandler<ChatroomKeyable> {
override suspend fun process( override suspend fun add(
event: Event, event: ChatroomKeyable,
eventNote: Note, eventNote: Note,
publicNote: Note, publicNote: Note,
) { ) {
event as PrivateDmEvent chatroomList.add(event, eventNote)
if (event.canDecrypt(chatroomService.account.signer.pubKey)) {
val key = event.chatroomKey(chatroomService.account.signer.pubKey)
chatroomService.addMessage(key, eventNote)
}
} }
override suspend fun delete( override suspend fun delete(
event: Event, event: ChatroomKeyable,
eventNote: Note, eventNote: Note,
) { ) {
event as PrivateDmEvent chatroomList.delete(event, eventNote)
if (event.canDecrypt(chatroomService.account.signer.pubKey)) {
val key = event.chatroomKey(chatroomService.account.signer.pubKey)
chatroomService.removeMessage(key, eventNote)
}
}
}
class ChatMessageHandler(
private val chatroomService: ChatroomService,
) : EventHandler {
override suspend fun process(
event: Event,
eventNote: Note,
publicNote: Note,
) {
event as ChatMessageEvent
if (event.isIncluded(chatroomService.account.signer.pubKey)) {
val key = event.chatroomKey(chatroomService.account.signer.pubKey)
chatroomService.addMessage(key, eventNote)
}
}
override suspend fun delete(
event: Event,
eventNote: Note,
) {
event as ChatMessageEvent
if (event.isIncluded(chatroomService.account.signer.pubKey)) {
val key = event.chatroomKey(chatroomService.account.signer.pubKey)
chatroomService.removeMessage(key, eventNote)
}
}
}
class ChatMessageEncryptedFileHeaderHandler(
private val chatroomService: ChatroomService,
) : EventHandler {
override suspend fun process(
event: Event,
eventNote: Note,
publicNote: Note,
) {
event as ChatMessageEncryptedFileHeaderEvent
if (event.isIncluded(chatroomService.account.signer.pubKey)) {
val key = event.chatroomKey(chatroomService.account.signer.pubKey)
chatroomService.addMessage(key, eventNote)
}
}
override suspend fun delete(
event: Event,
eventNote: Note,
) {
event as ChatMessageEncryptedFileHeaderEvent
if (event.isIncluded(chatroomService.account.signer.pubKey)) {
val key = event.chatroomKey(chatroomService.account.signer.pubKey)
chatroomService.removeMessage(key, eventNote)
}
} }
} }
class OtsEventHandler( class OtsEventHandler(
private val account: Account, private val account: Account,
) : EventHandler { ) : EventHandler<OtsEvent> {
override suspend fun process( override suspend fun add(
event: Event, event: OtsEvent,
eventNote: Note, eventNote: Note,
publicNote: Note, publicNote: Note,
) { ) {
event as OtsEvent
Amethyst.instance.otsVerifCache.cacheVerify(event, account.otsResolverBuilder) Amethyst.instance.otsVerifCache.cacheVerify(event, account.otsResolverBuilder)
} }
} }
class DraftEventHandler( class DraftEventHandler(
private val decryptionService: DecryptionService, private val account: Account,
private val indexingService: IndexingService, private val indexingService: IndexingService,
) : EventHandler { ) : EventHandler<DraftEvent> {
override suspend fun process( override suspend fun add(
event: Event, event: DraftEvent,
eventNote: Note, eventNote: Note,
publicNote: Note, publicNote: Note,
) { ) {
event as DraftEvent if (event.pubKey == account.signer.pubKey && !event.isDeleted()) {
if (event.pubKey == decryptionService.account.signer.pubKey && !event.isDeleted()) { val rumor = account.draftsDecryptionCache.preCachedDraft(event) ?: account.draftsDecryptionCache.cachedDraft(event)
val rumor = decryptionService.decryptDraft(event)
rumor?.let { indexingService.indexDraftAsRealEvent(eventNote, it) } rumor?.let { indexingService.indexDraftAsRealEvent(eventNote, it) }
} }
} }
} }
class GiftWrapEventHandler( class GiftWrapEventHandler(
private val decryptionService: DecryptionService, private val account: Account,
private val cache: LocalCache, private val cache: LocalCache,
private val eventProcessor: EventProcessor, private val eventProcessor: EventProcessor,
) : EventHandler { ) : EventHandler<GiftWrapEvent> {
override suspend fun process( override suspend fun add(
event: Event, event: GiftWrapEvent,
eventNote: Note, eventNote: Note,
publicNote: Note, publicNote: Note,
) { ) {
event as GiftWrapEvent if (event.recipientPubKey() != account.signer.pubKey) return
if (event.recipientPubKey() != decryptionService.account.signer.pubKey) return
val innerGiftId = event.innerEventId val innerGiftId = event.innerEventId
if (innerGiftId == null) { if (innerGiftId == null) {
@@ -395,11 +264,10 @@ class GiftWrapEventHandler(
} }
override suspend fun delete( override suspend fun delete(
event: Event, event: GiftWrapEvent,
eventNote: Note, eventNote: Note,
) { ) {
event as GiftWrapEvent if (event.recipientPubKey() != account.signer.pubKey) return
if (event.recipientPubKey() != decryptionService.account.signer.pubKey) return
event.innerEventId?.let { innerGiftId -> event.innerEventId?.let { innerGiftId ->
val innerGiftNote = cache.getNoteIfExists(innerGiftId) val innerGiftNote = cache.getNoteIfExists(innerGiftId)
@@ -414,13 +282,13 @@ class GiftWrapEventHandler(
eventNote: Note, eventNote: Note,
publicNote: Note, publicNote: Note,
) { ) {
val innerGift = decryptionService.unwrapGiftWrap(event) ?: return val innerGift = event.unwrapOrNull(account.signer) ?: return
eventNote.event = event.copyNoContent() eventNote.event = event.copyNoContent()
if (cache.justConsume(innerGift, null, false)) { if (cache.justConsume(innerGift, null, false)) {
cache.copyRelaysFromTo(publicNote, innerGift) cache.copyRelaysFromTo(publicNote, innerGift)
val innerGiftNote = cache.getOrCreateNote(innerGift.id) val innerGiftNote = cache.getOrCreateNote(innerGift.id)
eventProcessor.processEvent(innerGift, innerGiftNote, publicNote) eventProcessor.consumeEvent(innerGift, innerGiftNote, publicNote)
} }
} }
@@ -431,23 +299,21 @@ class GiftWrapEventHandler(
cache.copyRelaysFromTo(publicNote, innerGiftId) cache.copyRelaysFromTo(publicNote, innerGiftId)
val innerGiftNote = cache.getOrCreateNote(innerGiftId) val innerGiftNote = cache.getOrCreateNote(innerGiftId)
innerGiftNote.event?.let { innerGift -> innerGiftNote.event?.let { innerGift ->
eventProcessor.processEvent(innerGift, innerGiftNote, publicNote) eventProcessor.consumeEvent(innerGift, innerGiftNote, publicNote)
} }
} }
} }
class SealedRumorEventHandler( class SealedRumorEventHandler(
private val decryptionService: DecryptionService, private val account: Account,
private val cache: LocalCache, private val cache: LocalCache,
private val eventProcessor: EventProcessor, private val eventProcessor: EventProcessor,
) : EventHandler { ) : EventHandler<SealedRumorEvent> {
override suspend fun process( override suspend fun add(
event: Event, event: SealedRumorEvent,
eventNote: Note, eventNote: Note,
publicNote: Note, publicNote: Note,
) { ) {
event as SealedRumorEvent
val rumorId = event.innerEventId val rumorId = event.innerEventId
if (rumorId == null) { if (rumorId == null) {
processNewSealedRumor(event, eventNote, publicNote) processNewSealedRumor(event, eventNote, publicNote)
@@ -457,11 +323,9 @@ class SealedRumorEventHandler(
} }
override suspend fun delete( override suspend fun delete(
event: Event, event: SealedRumorEvent,
eventNote: Note, eventNote: Note,
) { ) {
event as SealedRumorEvent
event.innerEventId?.let { rumorId -> event.innerEventId?.let { rumorId ->
val innerRumorNote = cache.getNoteIfExists(rumorId) val innerRumorNote = cache.getNoteIfExists(rumorId)
innerRumorNote?.event?.let { innerRumor -> innerRumorNote?.event?.let { innerRumor ->
@@ -475,14 +339,14 @@ class SealedRumorEventHandler(
eventNote: Note, eventNote: Note,
publicNote: Note, publicNote: Note,
) { ) {
val innerRumor = decryptionService.unsealRumor(event) ?: return val innerRumor = event.unsealOrNull(account.signer) ?: return
eventNote.event = event.copyNoContent() eventNote.event = event.copyNoContent()
cache.justConsume(innerRumor, null, true) cache.justConsume(innerRumor, null, true)
cache.copyRelaysFromTo(publicNote, innerRumor) cache.copyRelaysFromTo(publicNote, innerRumor)
val innerRumorNote = cache.getOrCreateNote(innerRumor.id) val innerRumorNote = cache.getOrCreateNote(innerRumor.id)
eventProcessor.processEvent(innerRumor, innerRumorNote, publicNote) eventProcessor.consumeEvent(innerRumor, innerRumorNote, publicNote)
} }
private suspend fun processExistingSealedRumor( private suspend fun processExistingSealedRumor(
@@ -492,40 +356,45 @@ class SealedRumorEventHandler(
cache.copyRelaysFromTo(publicNote, rumorId) cache.copyRelaysFromTo(publicNote, rumorId)
val innerRumorNote = cache.getOrCreateNote(rumorId) val innerRumorNote = cache.getOrCreateNote(rumorId)
innerRumorNote.event?.let { innerRumor -> innerRumorNote.event?.let { innerRumor ->
eventProcessor.processEvent(innerRumor, innerRumorNote, publicNote) eventProcessor.consumeEvent(innerRumor, innerRumorNote, publicNote)
} }
} }
} }
class LnZapRequestEventHandler( class LnZapRequestEventHandler(
private val decryptionService: DecryptionService, val decryptionCache: PrivateZapCache,
) : EventHandler { ) : EventHandler<LnZapRequestEvent> {
override suspend fun process( override suspend fun add(
event: Event, event: LnZapRequestEvent,
eventNote: Note, eventNote: Note,
publicNote: Note, publicNote: Note,
) { ) {
event as LnZapRequestEvent if (decryptionCache.cachedPrivateZap(event) == null && event.isPrivateZap()) {
decryptionService.handlePrivateZap(event) decryptionCache.decryptPrivateZap(event)
}
} }
override suspend fun delete( override suspend fun delete(
event: Event, event: LnZapRequestEvent,
eventNote: Note, eventNote: Note,
) { ) {
event as LnZapRequestEvent if (event.isPrivateZap()) {
decryptionService.deletePrivateZap(event) decryptionCache.delete(event)
}
} }
} }
class LnZapEventHandler( class LnZapEventHandler(
private val decryptionService: DecryptionService, val decryptionCache: PrivateZapCache,
) : EventHandler { ) : EventHandler<LnZapEvent> {
override suspend fun delete( override suspend fun delete(
event: Event, event: LnZapEvent,
eventNote: Note, eventNote: Note,
) { ) {
event as LnZapEvent event.zapRequest?.let { req ->
decryptionService.deletePrivateZapFromZapEvent(event) if (req.isPrivateZap()) {
decryptionCache.delete(req)
}
}
} }
} }

View File

@@ -31,7 +31,7 @@ class PrivateDMCache(
private val decryptionCache = private val decryptionCache =
object : LruCache<PrivateDmEvent, PrivateDMDecryptCache>(10000) { object : LruCache<PrivateDmEvent, PrivateDMDecryptCache>(10000) {
override fun create(key: PrivateDmEvent): PrivateDMDecryptCache? { override fun create(key: PrivateDmEvent): PrivateDMDecryptCache? {
val canDecrypt = key.canDecrypt(signer.pubKey) val canDecrypt = key.isIncluded(signer.pubKey)
return if (key.content.isNotBlank() && canDecrypt) { return if (key.content.isNotBlank() && canDecrypt) {
PrivateDMDecryptCache(signer) PrivateDMDecryptCache(signer)
} else { } else {

View File

@@ -58,12 +58,12 @@ class PrivateDmEvent(
override fun isContentEncoded() = true override fun isContentEncoded() = true
fun canDecrypt(signer: NostrSigner) = canDecrypt(signer.pubKey) fun isIncluded(signer: NostrSigner) = isIncluded(signer.pubKey)
fun canDecrypt(signerPubKey: HexKey) = pubKey == signerPubKey || recipientPubKey() == signerPubKey override fun isIncluded(user: HexKey) = pubKey == user || recipientPubKey() == user
suspend fun decryptContent(signer: NostrSigner): String { suspend fun decryptContent(signer: NostrSigner): String {
if (!canDecrypt(signer.pubKey)) throw SignerExceptions.UnauthorizedDecryptionException() if (!isIncluded(signer.pubKey)) throw SignerExceptions.UnauthorizedDecryptionException()
val retVal = signer.decrypt(content, talkingWith(signer.pubKey)) val retVal = signer.decrypt(content, talkingWith(signer.pubKey))
return if (retVal.startsWith(NIP_18_ADVERTISEMENT)) { return if (retVal.startsWith(NIP_18_ADVERTISEMENT)) {

View File

@@ -21,7 +21,10 @@
package com.vitorpamplona.quartz.nip17Dm.base package com.vitorpamplona.quartz.nip17Dm.base
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.IEvent
interface ChatroomKeyable : IEvent {
fun isIncluded(user: HexKey): Boolean
interface ChatroomKeyable {
fun chatroomKey(toRemove: HexKey): ChatroomKey fun chatroomKey(toRemove: HexKey): ChatroomKey
} }