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): { kind: number created_at: number tags: string[][] content: string } { return { kind: 4, created_at: Math.floor(Date.now() / 1000), tags: [ ['p', recipientPubkey], ['e', articleId], ], content: encryptedKey, } } async function publishEncryptedMessage(params: { articleId: string recipientPubkey: string authorPubkey: string authorPrivateKey: string keyData: string }): Promise<{ eventId: string } | null> { const encryptedKey = await Promise.resolve(nip04.encrypt(params.authorPrivateKey, params.recipientPubkey, params.keyData)) const privateMessageEvent = buildPrivateMessageEvent(params.recipientPubkey, params.articleId, encryptedKey) const publishedEvent = await nostrService.publishEvent(privateMessageEvent) if (!publishedEvent) { console.error('Failed to publish private message event', { articleId: params.articleId, recipientPubkey: params.recipientPubkey, authorPubkey: params.authorPubkey }) return null } console.warn('Private message published', { messageEventId: publishedEvent.id, articleId: params.articleId, recipientPubkey: params.recipientPubkey, authorPubkey: params.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 { try { nostrService.setPrivateKey(authorPrivateKey) nostrService.setPublicKey(storedContent.authorPubkey) const keyData = prepareKeyData(storedContent) const publishResult = await publishEncryptedMessage({ articleId, recipientPubkey, authorPubkey: 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 } } }