mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-11-10 18:56:55 +01:00
Simplifying the refactoring of the DecryptAndIndexProcessor
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user