import type { ArticleDraft } from '../articlePublisher' import type { AlbyInvoice } from '@/types/alby' import type { Article } from '@/types/nostr' import { createArticleInvoice } from '../articleInvoice' import { storePrivateContent } from '../articleStorage' import { buildTags } from '../nostrTagSystem' import { PLATFORM_SERVICE } from '../platformConfig' import { generatePublicationHashId } from '../hashIdGenerator' import { ensureKeys, ensurePresentation, mapDraftCategoryToTag, requireCategory } from './shared' import { buildParsedArticleFromDraft, publishPreviewWithInvoice } from './publicationPreview' import type { ArticleUpdateResult } from './types' export async function publishArticleUpdate( originalArticleId: string, draft: ArticleDraft, authorPubkey: string, authorPrivateKey?: string ): Promise { try { ensureKeys(authorPubkey, authorPrivateKey) return publishUpdate(draft, authorPubkey, originalArticleId) } catch (error) { return updateFailure(originalArticleId, error instanceof Error ? error.message : 'Unknown error') } } async function publishUpdate(draft: ArticleDraft, authorPubkey: string, originalArticleId: string): Promise { requireCategory(draft.category) const originalArticle = await loadOriginalArticleForUpdate(originalArticleId) if (!originalArticle) { return updateFailure(originalArticleId, 'Original article not found in cache') } if (originalArticle.pubkey !== authorPubkey) { return updateFailure(originalArticleId, 'Only the author can update this article') } const presentationId = await ensurePresentation(authorPubkey) const invoice = await createArticleInvoice(draft) const newCategory = mapDraftCategoryToTag(draft.category) const currentVersion = originalArticle.version ?? 0 const updateTags = await buildUpdateTags({ draft, originalArticleId, newCategory, authorPubkey, currentVersion }) const updatedArticle = await buildUpdatedArticleForUpdate({ draft, invoice, authorPubkey, currentVersion }) const publishedEvent = await publishPreviewWithInvoice({ draft, invoice, authorPubkey, presentationId, extraTags: updateTags, customArticle: updatedArticle }) if (!publishedEvent) { return updateFailure(originalArticleId, 'Failed to publish article update') } await storePrivateContent({ articleId: publishedEvent.id, content: draft.content, authorPubkey, invoice }) return { articleId: publishedEvent.id, previewEventId: publishedEvent.id, invoice, success: true, originalArticleId } } async function buildUpdateTags(params: { draft: ArticleDraft originalArticleId: string newCategory: 'sciencefiction' | 'research' authorPubkey: string currentVersion?: number }): Promise { const hashId = await generatePublicationHashId({ pubkey: params.authorPubkey, title: params.draft.title, preview: params.draft.preview, category: params.newCategory, seriesId: params.draft.seriesId ?? undefined, bannerUrl: params.draft.bannerUrl ?? undefined, zapAmount: params.draft.zapAmount, }) const currentVersion = params.currentVersion ?? 0 const nextVersion = currentVersion + 1 const updateTags = buildTags({ type: 'publication', category: params.newCategory, id: hashId, service: PLATFORM_SERVICE, version: nextVersion, hidden: false, paywall: true, title: params.draft.title, preview: params.draft.preview, zapAmount: params.draft.zapAmount, ...(params.draft.seriesId ? { seriesId: params.draft.seriesId } : {}), ...(params.draft.bannerUrl ? { bannerUrl: params.draft.bannerUrl } : {}), }) updateTags.push(['e', params.originalArticleId], ['replace', 'article-update']) return updateTags } async function loadOriginalArticleForUpdate(originalArticleId: string): Promise
{ const { objectCache } = await import('../objectCache') return (await objectCache.getById('publication', originalArticleId)) as Article | null } async function buildUpdatedArticleForUpdate(params: { draft: ArticleDraft; invoice: AlbyInvoice; authorPubkey: string; currentVersion: number }): Promise
{ const { article } = await buildParsedArticleFromDraft(params.draft, params.invoice, params.authorPubkey) return { ...article, version: params.currentVersion + 1 } } function updateFailure(originalArticleId: string, error?: string): ArticleUpdateResult { return { articleId: '', previewEventId: '', success: false, originalArticleId, ...(error ? { error } : {}) } }