diff --git a/src/client.ts b/src/client.ts index e336116..0c55d64 100644 --- a/src/client.ts +++ b/src/client.ts @@ -29,6 +29,7 @@ function getPool(): Pool { /** Get events from a NIP-01 filter. */ function getFilters(filters: Filter[], opts: GetFiltersOpts = {}): Promise[]> { + if (!filters.length) return Promise.resolve([]); return new Promise((resolve) => { let tid: number; const results: Event[] = []; diff --git a/src/controllers/api/timelines.ts b/src/controllers/api/timelines.ts index 82e1cf3..6a442c1 100644 --- a/src/controllers/api/timelines.ts +++ b/src/controllers/api/timelines.ts @@ -1,4 +1,6 @@ +import { z } from '@/deps.ts'; import { getFeed, getPublicFeed } from '@/queries.ts'; +import { booleanParamSchema } from '@/schema.ts'; import { toStatus } from '@/transformers/nostr-to-mastoapi.ts'; import { buildLinkHeader, paginationSchema } from '@/utils.ts'; @@ -19,10 +21,15 @@ const homeController: AppController = async (c) => { return c.json(statuses, 200, link ? { link } : undefined); }; +const publicQuerySchema = z.object({ + local: booleanParamSchema.catch(false), +}); + const publicController: AppController = async (c) => { const params = paginationSchema.parse(c.req.query()); + const { local } = publicQuerySchema.parse(c.req.query()); - const events = await getPublicFeed(params); + const events = await getPublicFeed(params, local); if (!events.length) { return c.json([]); } diff --git a/src/db/events.ts b/src/db/events.ts index 7910a40..4538636 100644 --- a/src/db/events.ts +++ b/src/db/events.ts @@ -64,7 +64,9 @@ function getFilterQuery(filter: DittoFilter) { ]) .orderBy('events.created_at', 'desc'); - for (const key of Object.keys(filter)) { + for (const [key, value] of Object.entries(filter)) { + if (value === undefined) continue; + switch (key as keyof DittoFilter) { case 'ids': query = query.where('events.id', 'in', filter.ids!); @@ -108,6 +110,7 @@ async function getFilters( filters: DittoFilter[], opts: GetFiltersOpts = {}, ): Promise[]> { + if (!filters.length) return Promise.resolve([]); let query = filters.map(getFilterQuery).reduce((acc, curr) => acc.union(curr)); if (typeof opts.limit === 'number') { diff --git a/src/mixer.ts b/src/mixer.ts index aed5311..c2e6b3a 100644 --- a/src/mixer.ts +++ b/src/mixer.ts @@ -12,7 +12,7 @@ async function getFilters( opts?: GetFiltersOpts, ): Promise[]> { const results = await Promise.allSettled([ - client.getFilters(filters, opts), + client.getFilters(filters.filter((filter) => !filter.local), opts), eventsDB.getFilters(filters, opts), ]); diff --git a/src/queries.ts b/src/queries.ts index 0f4b3ec..9e17008 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -57,8 +57,8 @@ async function getFeed(pubkey: string, params: PaginationParams): Promise[]> { - return mixer.getFilters([{ kinds: [1], ...params }], { timeout: 5000 }); +function getPublicFeed(params: PaginationParams, local: boolean): Promise[]> { + return mixer.getFilters([{ kinds: [1], local, ...params }], { timeout: 5000 }); } async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise[]> { diff --git a/src/schema.ts b/src/schema.ts index e56c1ae..3ecc76a 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -42,4 +42,7 @@ const hashtagSchema = z.string().regex(/^\w{1,30}$/); */ const safeUrlSchema = z.string().max(2048).url(); -export { decode64Schema, emojiTagSchema, filteredArray, hashtagSchema, jsonSchema, safeUrlSchema }; +/** https://github.com/colinhacks/zod/issues/1630#issuecomment-1365983831 */ +const booleanParamSchema = z.enum(['true', 'false']).transform((value) => value === 'true'); + +export { booleanParamSchema, decode64Schema, emojiTagSchema, filteredArray, hashtagSchema, jsonSchema, safeUrlSchema };