diff --git a/src/filter.ts b/src/filter.ts index 7f3cb4f..926e360 100644 --- a/src/filter.ts +++ b/src/filter.ts @@ -14,8 +14,12 @@ interface DittoFilter extends Filter { relations?: Relation[]; } +/** Microfilter to get one specific event by ID. */ +type IdMicrofilter = { ids: [Event['id']] }; +/** Microfilter to get an author. */ +type AuthorMicrofilter = { kinds: [0]; authors: [Event['pubkey']] }; /** Filter to get one specific event. */ -type MicroFilter = { ids: [Event['id']] } | { kinds: [0]; authors: [Event['pubkey']] }; +type MicroFilter = IdMicrofilter | AuthorMicrofilter; /** Additional options to apply to the whole subscription. */ interface GetFiltersOpts { @@ -89,11 +93,13 @@ function isMicrofilter(filter: Filter): filter is MicroFilter { } export { + type AuthorMicrofilter, type DittoFilter, eventToMicroFilter, getFilterId, type GetFiltersOpts, getMicroFilters, + type IdMicrofilter, isMicrofilter, matchDittoFilters, type MicroFilter, diff --git a/src/queries.ts b/src/queries.ts index 3af2253..9e7b4ce 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -1,8 +1,9 @@ import * as eventsDB from '@/db/events.ts'; import { type Event, findReplyTag } from '@/deps.ts'; -import { type DittoFilter, type Relation } from '@/filter.ts'; +import { AuthorMicrofilter, type DittoFilter, type Relation } from '@/filter.ts'; import * as mixer from '@/mixer.ts'; import { reqmeister } from '@/reqmeister.ts'; +import { memorelay } from '@/db/memorelay.ts'; interface GetEventOpts { /** Signal to abort the request. */ @@ -30,13 +31,22 @@ const getEvent = async ( /** Get a Nostr `set_medatadata` event for a user's pubkey. */ const getAuthor = async (pubkey: string, opts: GetEventOpts<0> = {}): Promise | undefined> => { const { relations, signal = AbortSignal.timeout(1000) } = opts; + const microfilter: AuthorMicrofilter = { kinds: [0], authors: [pubkey] }; - const event = await eventsDB.getFilters( + let event: Event<0> | undefined; + + [event] = await memorelay.getFilters([microfilter], opts); + + if (event) return event; + + [event] = await eventsDB.getFilters( [{ authors: [pubkey], relations, kinds: [0], limit: 1 }], { limit: 1, signal }, - ).then(([event]) => event) || await reqmeister.req({ kinds: [0], authors: [pubkey] }).catch(() => {}); + ); - return event; + if (event) return event; + + return reqmeister.req({ kinds: [0], authors: [pubkey] }).catch(() => undefined); }; /** Get users the given pubkey follows. */ diff --git a/src/reqmeister.ts b/src/reqmeister.ts index d8fef75..6019758 100644 --- a/src/reqmeister.ts +++ b/src/reqmeister.ts @@ -1,6 +1,6 @@ import * as client from '@/client.ts'; import { Debug, type Event, EventEmitter, type Filter } from '@/deps.ts'; -import { eventToMicroFilter, getFilterId, type MicroFilter } from '@/filter.ts'; +import { AuthorMicrofilter, eventToMicroFilter, getFilterId, IdMicrofilter, type MicroFilter } from '@/filter.ts'; import { Time } from '@/utils/time.ts'; const debug = Debug('ditto:reqmeister'); @@ -70,6 +70,9 @@ class Reqmeister extends EventEmitter<{ [filterId: string]: (event: Event) => an this.#perform(); } + req(filter: IdMicrofilter, relays?: WebSocket['url'][]): Promise; + req(filter: AuthorMicrofilter, relays?: WebSocket['url'][]): Promise>; + req(filter: MicroFilter, relays?: WebSocket['url'][]): Promise; req(filter: MicroFilter, relays: WebSocket['url'][] = []): Promise { const filterId = getFilterId(filter); this.#queue.push([filterId, filter, relays]);