123 lines
4.6 KiB
TypeScript
123 lines
4.6 KiB
TypeScript
import type { Event, Filter } from 'nostr-tools'
|
|
import type { SimplePoolWithSub } from '@/types/nostr-tools-extended'
|
|
import { createSubscription } from '@/types/nostr-tools-extended'
|
|
import { buildTagFilter, extractTagsFromEvent } from '../nostrTagSystem'
|
|
import { getPrimaryRelaySync } from '../config'
|
|
import { MIN_EVENT_DATE, PLATFORM_SERVICE } from '../platformConfig'
|
|
import { getLatestVersion } from '../versionManager'
|
|
import { objectCache } from '../objectCache'
|
|
import { parsePresentationEvent } from './parsePresentationEvent'
|
|
|
|
export async function fetchAuthorPresentationFromPool(
|
|
pool: SimplePoolWithSub,
|
|
pubkey: string
|
|
): Promise<import('@/types/nostr').AuthorPresentationArticle | null> {
|
|
const cached = await objectCache.getAuthorByPubkey(pubkey)
|
|
if (cached) {
|
|
return enrichAuthorPresentationWithSponsoring({ author: cached, pubkey })
|
|
}
|
|
const filters: Filter[] = [
|
|
{
|
|
...buildTagFilter({ type: 'author', authorPubkey: pubkey, service: PLATFORM_SERVICE }),
|
|
since: MIN_EVENT_DATE,
|
|
limit: 100,
|
|
},
|
|
]
|
|
return fetchAuthorPresentationFromRelay({ pool, pubkey, filters })
|
|
}
|
|
|
|
async function enrichAuthorPresentationWithSponsoring(params: {
|
|
author: import('@/types/nostr').AuthorPresentationArticle
|
|
pubkey: string
|
|
}): Promise<import('@/types/nostr').AuthorPresentationArticle> {
|
|
const { getAuthorSponsoring } = await import('../sponsoring')
|
|
const totalSponsoring = await getAuthorSponsoring(params.pubkey)
|
|
return { ...params.author, totalSponsoring }
|
|
}
|
|
|
|
async function fetchAuthorPresentationFromRelay(params: {
|
|
pool: SimplePoolWithSub
|
|
pubkey: string
|
|
filters: Filter[]
|
|
}): Promise<import('@/types/nostr').AuthorPresentationArticle | null> {
|
|
const relayUrl = getPrimaryRelaySync()
|
|
const events: Event[] = []
|
|
const sub = createSubscription(params.pool, [relayUrl], params.filters)
|
|
const finalize = createRelayFetchFinalizer({ pubkey: params.pubkey, sub, events })
|
|
|
|
return new Promise<import('@/types/nostr').AuthorPresentationArticle | null>((resolve) => {
|
|
const finalizeAndResolve = async (value: import('@/types/nostr').AuthorPresentationArticle | null): Promise<void> => {
|
|
const finalValue = await finalize(value)
|
|
resolve(finalValue)
|
|
}
|
|
sub.on('event', (event: Event): void => {
|
|
const tags = extractTagsFromEvent(event)
|
|
if (tags.type === 'author' && !tags.hidden) {
|
|
events.push(event)
|
|
}
|
|
})
|
|
sub.on('eose', (): void => {
|
|
void tryFinalizeFromLatestEvent({ events, finalize: finalizeAndResolve })
|
|
})
|
|
setTimeout((): void => {
|
|
void tryFinalizeFromLatestEvent({ events, finalize: finalizeAndResolve })
|
|
}, 2000).unref?.()
|
|
})
|
|
}
|
|
|
|
async function tryFinalizeFromLatestEvent(params: {
|
|
events: Event[]
|
|
finalize: (value: import('@/types/nostr').AuthorPresentationArticle | null) => Promise<void>
|
|
}): Promise<void> {
|
|
const latestEvent = getLatestVersion(params.events)
|
|
if (!latestEvent) {
|
|
await params.finalize(null)
|
|
return
|
|
}
|
|
const parsed = await parsePresentationEvent(latestEvent)
|
|
await params.finalize(parsed)
|
|
}
|
|
|
|
function createRelayFetchFinalizer(params: {
|
|
pubkey: string
|
|
sub: import('@/types/nostr-tools-extended').Subscription
|
|
events: Event[]
|
|
}): (value: import('@/types/nostr').AuthorPresentationArticle | null) => Promise<import('@/types/nostr').AuthorPresentationArticle | null> {
|
|
let resolved = false
|
|
return async (value: import('@/types/nostr').AuthorPresentationArticle | null): Promise<import('@/types/nostr').AuthorPresentationArticle | null> => {
|
|
if (resolved) {
|
|
return value
|
|
}
|
|
resolved = true
|
|
params.sub.unsub()
|
|
return cacheAuthorPresentationFromEvents({ value, events: params.events, pubkey: params.pubkey })
|
|
}
|
|
}
|
|
|
|
async function cacheAuthorPresentationFromEvents(params: {
|
|
value: import('@/types/nostr').AuthorPresentationArticle | null
|
|
events: Event[]
|
|
pubkey: string
|
|
}): Promise<import('@/types/nostr').AuthorPresentationArticle | null> {
|
|
if (!params.value || params.events.length === 0 || !params.value.hash) {
|
|
return params.value
|
|
}
|
|
const event = params.events.find((e) => e.id === params.value?.id) ?? params.events[0]
|
|
if (!event) {
|
|
return params.value
|
|
}
|
|
const tags = extractTagsFromEvent(event)
|
|
const cachedValue = await enrichAuthorPresentationWithSponsoring({ author: params.value, pubkey: params.pubkey })
|
|
const { writeObjectToCache } = await import('../helpers/writeObjectHelper')
|
|
await writeObjectToCache({
|
|
objectType: 'author',
|
|
hash: params.value.hash,
|
|
event,
|
|
parsed: cachedValue,
|
|
version: tags.version,
|
|
hidden: tags.hidden,
|
|
index: params.value.index,
|
|
})
|
|
return cachedValue
|
|
}
|