87 lines
3.0 KiB
TypeScript
87 lines
3.0 KiB
TypeScript
import { nip04 } from 'nostr-tools'
|
|
import { nostrService } from './nostr'
|
|
import { publishAndVerifyMessage } from './articlePublisherHelpersVerification'
|
|
|
|
export interface SendContentResult {
|
|
success: boolean
|
|
messageEventId?: string
|
|
error?: string
|
|
verified?: boolean
|
|
}
|
|
|
|
export function prepareKeyData(storedContent: { content: string; decryptionKey?: string; decryptionIV?: string }): string {
|
|
if (storedContent.decryptionKey && storedContent.decryptionIV) {
|
|
return JSON.stringify({ key: storedContent.decryptionKey, iv: storedContent.decryptionIV })
|
|
}
|
|
return storedContent.content // Fallback to old behavior if keys are not available
|
|
}
|
|
|
|
export function buildPrivateMessageEvent(recipientPubkey: string, articleId: string, encryptedKey: string) {
|
|
return {
|
|
kind: 4,
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
tags: [
|
|
['p', recipientPubkey],
|
|
['e', articleId],
|
|
],
|
|
content: encryptedKey,
|
|
}
|
|
}
|
|
|
|
async function publishEncryptedMessage(
|
|
articleId: string,
|
|
recipientPubkey: string,
|
|
authorPubkey: string,
|
|
authorPrivateKey: string,
|
|
keyData: string
|
|
): Promise<{ eventId: string } | null> {
|
|
const encryptedKey = await Promise.resolve(nip04.encrypt(authorPrivateKey, recipientPubkey, keyData))
|
|
const privateMessageEvent = buildPrivateMessageEvent(recipientPubkey, articleId, encryptedKey)
|
|
const publishedEvent = await nostrService.publishEvent(privateMessageEvent)
|
|
|
|
if (!publishedEvent) {
|
|
console.error('Failed to publish private message event', { articleId, recipientPubkey, authorPubkey })
|
|
return null
|
|
}
|
|
|
|
console.log('Private message published', {
|
|
messageEventId: publishedEvent.id,
|
|
articleId,
|
|
recipientPubkey,
|
|
authorPubkey,
|
|
timestamp: new Date().toISOString(),
|
|
})
|
|
return { eventId: publishedEvent.id }
|
|
}
|
|
|
|
export async function sendEncryptedContent(
|
|
articleId: string,
|
|
recipientPubkey: string,
|
|
storedContent: { content: string; authorPubkey: string; decryptionKey?: string; decryptionIV?: string },
|
|
authorPrivateKey: string
|
|
): Promise<SendContentResult> {
|
|
try {
|
|
nostrService.setPrivateKey(authorPrivateKey)
|
|
nostrService.setPublicKey(storedContent.authorPubkey)
|
|
|
|
const keyData = prepareKeyData(storedContent)
|
|
const publishResult = await publishEncryptedMessage(articleId, recipientPubkey, storedContent.authorPubkey, authorPrivateKey, keyData)
|
|
if (!publishResult) {
|
|
return { success: false, error: 'Failed to publish private message event' }
|
|
}
|
|
|
|
const verified = await publishAndVerifyMessage(articleId, recipientPubkey, storedContent.authorPubkey, publishResult.eventId)
|
|
return { success: true, messageEventId: publishResult.eventId, verified }
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
|
console.error('Error sending encrypted content', {
|
|
articleId,
|
|
recipientPubkey,
|
|
authorPubkey: storedContent.authorPubkey,
|
|
error: errorMessage,
|
|
timestamp: new Date().toISOString(),
|
|
})
|
|
return { success: false, error: errorMessage }
|
|
}
|
|
}
|