import { Func, Inbox, Lifecycle, spawn, loop, STOP } from 'anneal' import { Event as NEvent, nip19 } from 'nostr-tools' import FlexSearch from 'flexsearch' export type UserIndexActor = { addProfile: Inbox search: Func<{ query: string; limit: number }, string[]> lc: Lifecycle } export function createUserIndexActor(): UserIndexActor { const index = new FlexSearch.Index({ tokenize: 'forward' }) const addProfile = new Inbox(0) const search = new Func<{ query: string; limit: number }, string[]>() const lc = new Lifecycle() spawn(lc, async () => { await loop( lc.on(() => STOP), addProfile.on((event) => { try { const obj = JSON.parse(event.content) const text = [ obj.display_name?.trim() ?? '', obj.name?.trim() ?? '', obj.nip05 ?.split('@') .map((s: string) => s.trim()) .join(' ') ?? '' ].join(' ') if (text) { index.add(event.pubkey, text) } } catch { // skip invalid profiles } }), search.on(({ req: { query, limit }, reply }) => { const result = index.search(query, { limit }) reply( result.map((pubkey) => nip19.npubEncode(pubkey as string)).filter(Boolean) as string[] ) }) ) }) return { addProfile, search, lc } }