story-research-zapwall/lib/nostrPrivateMessages.ts
Nicolas Cantu 3000872dbc refactoring
- **Motivations :** Assurer passage du lint strict et clarifier la logique paiements/publications.

- **Root causes :** Fonctions trop longues, promesses non gérées et typages WebLN/Nostr incomplets.

- **Correctifs :** Refactor PaymentModal (handlers void), extraction helpers articlePublisher, simplification polling sponsoring/zap, corrections curly et awaits.

- **Evolutions :** Nouveau module articlePublisherHelpers pour présentation/aiguillage contenu privé.

- **Page affectées :** components/PaymentModal.tsx, lib/articlePublisher.ts, lib/articlePublisherHelpers.ts, lib/paymentPolling.ts, lib/sponsoring.ts, lib/nostrZapVerification.ts et dépendances liées.
2025-12-22 17:56:00 +01:00

66 lines
1.8 KiB
TypeScript

import { Event, nip04 } from 'nostr-tools'
import { SimplePool } from 'nostr-tools'
const RELAY_URL = process.env.NEXT_PUBLIC_NOSTR_RELAY_URL ?? 'wss://relay.damus.io'
function createPrivateMessageFilters(eventId: string, publicKey: string, authorPubkey: string) {
return [
{
kinds: [4], // Encrypted direct messages
'#p': [publicKey],
'#e': [eventId], // Filter by event ID to find relevant private messages
authors: [authorPubkey], // Filter by author of the original article
limit: 10, // Limit to recent messages
},
]
}
function decryptContent(privateKey: string, event: Event): Promise<string | null> {
return Promise.resolve(nip04.decrypt(privateKey, event.pubkey, event.content)).then((decrypted) =>
decrypted ? decrypted : null
)
}
/**
* Get private content for an article (encrypted message from author)
*/
export function getPrivateContent(
pool: SimplePool,
eventId: string,
authorPubkey: string,
privateKey: string,
publicKey: string
): Promise<string | null> {
if (!privateKey || !pool || !publicKey) {
throw new Error('Private key not set or pool not initialized')
}
return new Promise((resolve) => {
let resolved = false
const sub = pool.sub([RELAY_URL], createPrivateMessageFilters(eventId, publicKey, authorPubkey))
const finalize = (result: string | null) => {
if (resolved) {
return
}
resolved = true
sub.unsub()
resolve(result)
}
sub.on('event', (event: Event) => {
void decryptContent(privateKey, event)
.then((content) => {
if (content) {
finalize(content)
}
})
.catch((e) => {
console.error('Error decrypting content:', e)
})
})
sub.on('eose', () => finalize(null))
setTimeout(() => finalize(null), 5000)
})
}