2026-01-13 14:49:19 +01:00

144 lines
4.8 KiB
TypeScript

import { buildTags } from '../nostrTagSystem'
import { PLATFORM_SERVICE } from '../platformConfig'
import { generateSeriesHashId } from '../hashIdGenerator'
import { buildObjectId } from '../urlGenerator'
import type { ArticleDraft } from '../articlePublisher'
import type { Series } from '@/types/nostr'
import { getPublishRelays } from '../relaySelection'
import { writeOrchestrator } from '../writeOrchestrator'
import { finalizeEvent } from 'nostr-tools'
import { hexToBytes } from 'nostr-tools/utils'
import type { EventTemplate } from 'nostr-tools'
import { ensureKeys, getPrivateKeyForSigning, mapDraftCategoryToTag, requireCategory } from './shared'
export async function publishSeries(params: {
title: string
description: string
preview?: string
coverUrl?: string
category: ArticleDraft['category']
authorPubkey: string
authorPrivateKey?: string
}): Promise<Series> {
ensureKeys(params.authorPubkey, params.authorPrivateKey)
const ctx = await buildSeriesPublishContext(params)
const event = finalizeEvent(ctx.eventTemplate, hexToBytes(getPrivateKeyForSigning(params.authorPrivateKey)))
await publishSeriesToRelays({ parsedSeries: ctx.parsedSeries, event })
return ctx.parsedSeries
}
function buildSeriesPreview(preview: string | undefined, description: string): string {
return preview ?? description.substring(0, 200)
}
async function buildSeriesPublishContext(params: {
title: string
description: string
preview?: string
coverUrl?: string
category: ArticleDraft['category']
authorPubkey: string
}): Promise<{ parsedSeries: Series; eventTemplate: EventTemplate }> {
requireCategory(params.category)
const newCategory = mapDraftCategoryToTag(params.category)
const preview = buildSeriesPreview(params.preview, params.description)
const hashId = await generateSeriesHashId({
pubkey: params.authorPubkey,
title: params.title,
description: params.description,
category: newCategory,
...(params.coverUrl ? { coverUrl: params.coverUrl } : {}),
})
const parsedSeries = buildParsedSeries({ authorPubkey: params.authorPubkey, title: params.title, description: params.description, preview, coverUrl: params.coverUrl, category: params.category, hashId })
const eventTemplate = buildSeriesEventTemplate({ authorPubkey: params.authorPubkey, title: params.title, description: params.description, preview, coverUrl: params.coverUrl, category: newCategory, hashId })
return { parsedSeries, eventTemplate }
}
async function publishSeriesToRelays(params: { parsedSeries: Series; event: import('nostr-tools').Event }): Promise<void> {
const relays = await getPublishRelays()
const result = await writeOrchestrator.writeAndPublish(
{ objectType: 'series', hash: params.parsedSeries.hash, event: params.event, parsed: params.parsedSeries, version: params.parsedSeries.version, hidden: false, index: params.parsedSeries.index },
relays
)
if (!result.success) {
throw new Error('Failed to publish series')
}
}
function buildParsedSeries(params: {
authorPubkey: string
title: string
description: string
preview: string
coverUrl: string | undefined
category: NonNullable<ArticleDraft['category']>
hashId: string
}): Series {
const hash = params.hashId
const version = 0
const index = 0
return {
id: buildObjectId(hash, index, version),
hash,
version,
index,
pubkey: params.authorPubkey,
title: params.title,
description: params.description,
preview: params.preview,
thumbnailUrl: params.coverUrl ?? '',
category: params.category,
...(params.coverUrl ? { coverUrl: params.coverUrl } : {}),
kindType: 'series',
}
}
function buildSeriesEventTemplate(params: {
authorPubkey: string
title: string
description: string
preview: string
coverUrl: string | undefined
category: 'sciencefiction' | 'research'
hashId: string
}): EventTemplate {
const tags = buildTags({
type: 'series',
category: params.category,
id: params.hashId,
service: PLATFORM_SERVICE,
version: 0,
hidden: false,
paywall: false,
title: params.title,
description: params.description,
preview: params.preview,
...(params.coverUrl ? { coverUrl: params.coverUrl } : {}),
})
tags.push(['json', buildSeriesJson(params)])
return { kind: 1, created_at: Math.floor(Date.now() / 1000), content: params.preview, tags }
}
function buildSeriesJson(params: {
authorPubkey: string
title: string
description: string
preview: string
coverUrl: string | undefined
category: 'sciencefiction' | 'research'
hashId: string
}): string {
return JSON.stringify({
type: 'series',
pubkey: params.authorPubkey,
title: params.title,
description: params.description,
preview: params.preview,
...(params.coverUrl ? { coverUrl: params.coverUrl } : {}),
category: params.category,
id: params.hashId,
version: 0,
index: 0,
})
}