story-research-zapwall/lib/articlePublisherPublish.ts

67 lines
2.5 KiB
TypeScript

import { nostrService } from './nostr'
import type { ArticleDraft, PublishedArticle } from './articlePublisherTypes'
import type { AlbyInvoice } from '@/types/alby'
import { createArticleInvoice, createPreviewEvent } from './articleInvoice'
import { encryptArticleContent, encryptDecryptionKey } from './articleEncryption'
import { storePrivateContent } from './articleStorage'
export function buildFailure(error?: string): PublishedArticle {
const base: PublishedArticle = {
articleId: '',
previewEventId: '',
success: false,
}
return error ? { ...base, error } : base
}
export async function publishPreview(
draft: ArticleDraft,
invoice: AlbyInvoice,
presentationId: string,
extraTags?: string[][],
encryptedContent?: string,
encryptedKey?: string
): Promise<import('nostr-tools').Event | null> {
const previewEvent = createPreviewEvent(draft, invoice, presentationId, extraTags, encryptedContent, encryptedKey)
const publishedEvent = await nostrService.publishEvent(previewEvent)
return publishedEvent ?? null
}
export function buildArticleExtraTags(draft: ArticleDraft, _category: NonNullable<ArticleDraft['category']>): string[][] {
// Media tags are still supported in the new system
const extraTags: string[][] = []
if (draft.media && draft.media.length > 0) {
draft.media.forEach((m) => {
extraTags.push(['media', m.url, m.type])
})
}
return extraTags
}
export async function encryptAndPublish(
draft: ArticleDraft,
authorPubkey: string,
authorPrivateKeyForEncryption: string,
category: NonNullable<ArticleDraft['category']>,
presentationId: string
): Promise<PublishedArticle> {
const { encryptedContent, key, iv } = await encryptArticleContent(draft.content)
const encryptedKey = await encryptDecryptionKey(key, iv, authorPrivateKeyForEncryption, authorPubkey)
const invoice = await createArticleInvoice(draft)
const extraTags = buildArticleExtraTags(draft, category)
const publishedEvent = await publishPreview(draft, invoice, presentationId, extraTags, encryptedContent, encryptedKey)
if (!publishedEvent) {
return buildFailure('Failed to publish article')
}
await storePrivateContent(publishedEvent.id, draft.content, authorPubkey, invoice, key, iv)
console.log('Article published with encrypted content', {
articleId: publishedEvent.id,
authorPubkey,
timestamp: new Date().toISOString(),
})
return { articleId: publishedEvent.id, previewEventId: publishedEvent.id, invoice, success: true }
}