67 lines
2.5 KiB
TypeScript
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 }
|
|
}
|