144 lines
4.8 KiB
TypeScript
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,
|
|
})
|
|
}
|