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 { 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 { 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 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, }) }