mirror of
https://github.com/dergigi/boris.git
synced 2026-02-16 20:45:01 +01:00
80 lines
2.6 KiB
TypeScript
80 lines
2.6 KiB
TypeScript
import { RelayPool, completeOnEose, onlyEvents } from 'applesauce-relay'
|
|
import { lastValueFrom, merge, Observable, takeUntil, timer, toArray, tap } from 'rxjs'
|
|
import { NostrEvent } from 'nostr-tools'
|
|
import { IEventStore } from 'applesauce-core'
|
|
import { prioritizeLocalRelays, partitionRelays } from '../utils/helpers'
|
|
import { rebroadcastEvents } from './rebroadcastService'
|
|
import { UserSettings } from './settingsService'
|
|
|
|
/**
|
|
* Fetches profile metadata (kind:0) for a list of pubkeys
|
|
* Stores profiles in the event store and optionally to local relays
|
|
*/
|
|
export const fetchProfiles = async (
|
|
relayPool: RelayPool,
|
|
eventStore: IEventStore,
|
|
pubkeys: string[],
|
|
settings?: UserSettings
|
|
): Promise<NostrEvent[]> => {
|
|
try {
|
|
if (pubkeys.length === 0) {
|
|
return []
|
|
}
|
|
|
|
const uniquePubkeys = Array.from(new Set(pubkeys))
|
|
|
|
const relayUrls = Array.from(relayPool.relays.values()).map(relay => relay.url)
|
|
const prioritized = prioritizeLocalRelays(relayUrls)
|
|
const { local: localRelays, remote: remoteRelays } = partitionRelays(prioritized)
|
|
|
|
// Keep only the most recent profile for each pubkey
|
|
const profilesByPubkey = new Map<string, NostrEvent>()
|
|
|
|
const processEvent = (event: NostrEvent) => {
|
|
const existing = profilesByPubkey.get(event.pubkey)
|
|
if (!existing || event.created_at > existing.created_at) {
|
|
profilesByPubkey.set(event.pubkey, event)
|
|
// Store in event store immediately
|
|
eventStore.add(event)
|
|
}
|
|
}
|
|
|
|
const local$ = localRelays.length > 0
|
|
? relayPool
|
|
.req(localRelays, { kinds: [0], authors: uniquePubkeys })
|
|
.pipe(
|
|
onlyEvents(),
|
|
tap((event: NostrEvent) => processEvent(event)),
|
|
completeOnEose(),
|
|
takeUntil(timer(1200))
|
|
)
|
|
: new Observable<NostrEvent>((sub) => sub.complete())
|
|
|
|
const remote$ = remoteRelays.length > 0
|
|
? relayPool
|
|
.req(remoteRelays, { kinds: [0], authors: uniquePubkeys })
|
|
.pipe(
|
|
onlyEvents(),
|
|
tap((event: NostrEvent) => processEvent(event)),
|
|
completeOnEose(),
|
|
takeUntil(timer(6000))
|
|
)
|
|
: new Observable<NostrEvent>((sub) => sub.complete())
|
|
|
|
await lastValueFrom(merge(local$, remote$).pipe(toArray()))
|
|
|
|
const profiles = Array.from(profilesByPubkey.values())
|
|
|
|
// Rebroadcast profiles to local/all relays based on settings
|
|
if (profiles.length > 0) {
|
|
await rebroadcastEvents(profiles, relayPool, settings)
|
|
}
|
|
|
|
return profiles
|
|
} catch (error) {
|
|
console.error('Failed to fetch profiles:', error)
|
|
return []
|
|
}
|
|
}
|
|
|