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

110 lines
3.7 KiB
TypeScript

import type { Event } from 'nostr-tools'
import { extractTagsFromEvent } from '../nostrTagSystem'
import { generatePublicationHashId } from '../hashIdGenerator'
import type { ExtractedPublication } from './types'
import { getMetadataFromEvent } from './metadataJson'
import { firstNumber, firstString } from './utils'
type PublicationPages = Array<{ number: number; type: 'markdown' | 'image'; content: string }>
export async function extractPublicationFromEvent(event: Event): Promise<ExtractedPublication | null> {
const tags = extractTagsFromEvent(event)
if (tags.type !== 'publication') {
return null
}
const metadata = getMetadataFromEvent(event)
if (metadata?.type === 'publication') {
const publicationData = buildPublicationDataFromMetadata({ event, tags, metadata })
const id = await generatePublicationHashId(publicationData)
const pages = readPublicationPages(metadata)
return buildExtractedPublication({ eventId: event.id, id, data: publicationData, pages })
}
if (!tags.title) {
return null
}
const publicationData = {
pubkey: event.pubkey,
title: tags.title,
preview: (tags.preview as string) ?? event.content.substring(0, 200),
category: tags.category ?? 'sciencefiction',
zapAmount: tags.zapAmount ?? 800,
...(tags.seriesId ? { seriesId: tags.seriesId } : {}),
...(tags.bannerUrl ? { bannerUrl: tags.bannerUrl } : {}),
}
const id = await generatePublicationHashId(publicationData)
return buildExtractedPublication({ eventId: event.id, id, data: publicationData, pages: undefined })
}
function buildPublicationDataFromMetadata(params: {
event: Event
tags: ReturnType<typeof extractTagsFromEvent>
metadata: Record<string, unknown>
}): {
pubkey: string
title: string
preview: string
category: string
seriesId?: string
bannerUrl?: string
zapAmount: number
} {
const base: {
pubkey: string
title: string
preview: string
category: string
seriesId?: string
bannerUrl?: string
zapAmount: number
} = {
pubkey: firstString(params.metadata.pubkey, params.event.pubkey) ?? params.event.pubkey,
title: firstString(params.metadata.title, params.tags.title) ?? '',
preview: firstString(params.metadata.preview, params.tags.preview) ?? params.event.content.substring(0, 200),
category: firstString(params.metadata.category, params.tags.category, 'sciencefiction') ?? 'sciencefiction',
zapAmount: firstNumber(params.metadata.zapAmount, params.tags.zapAmount) ?? 800,
}
const seriesId = firstString(params.metadata.seriesId, params.tags.seriesId)
if (seriesId) {
base.seriesId = seriesId
}
const bannerUrl = firstString(params.metadata.bannerUrl, params.tags.bannerUrl)
if (bannerUrl) {
base.bannerUrl = bannerUrl
}
return base
}
function readPublicationPages(metadata: Record<string, unknown>): PublicationPages | undefined {
const pages = metadata.pages as PublicationPages | undefined
return pages && Array.isArray(pages) && pages.length > 0 ? pages : undefined
}
function buildExtractedPublication(params: {
eventId: string
id: string
data: {
pubkey: string
title: string
preview: string
category: string
seriesId?: string
bannerUrl?: string
zapAmount: number
}
pages: PublicationPages | undefined
}): ExtractedPublication {
return {
type: 'publication',
id: params.id,
pubkey: params.data.pubkey,
title: params.data.title,
preview: params.data.preview,
category: params.data.category,
zapAmount: params.data.zapAmount,
eventId: params.eventId,
...(params.data.seriesId ? { seriesId: params.data.seriesId } : {}),
...(params.data.bannerUrl ? { bannerUrl: params.data.bannerUrl } : {}),
...(params.pages ? { pages: params.pages } : {}),
}
}