diff --git a/src/controllers/nostr/relay.ts b/src/controllers/nostr/relay.ts index c2882090..534150f0 100644 --- a/src/controllers/nostr/relay.ts +++ b/src/controllers/nostr/relay.ts @@ -41,6 +41,7 @@ function prepareFilters(filters: ClientREQ[2][]): Filter[] { return filters.map((filter) => ({ ...filter, limit: Math.min(filter.limit || FILTER_LIMIT, FILTER_LIMIT), + local: true, })); } diff --git a/src/db/events.ts b/src/db/events.ts index beb057e0..4d14f837 100644 --- a/src/db/events.ts +++ b/src/db/events.ts @@ -50,7 +50,11 @@ function insertEvent(event: SignedEvent): Promise { }); } -function getFilterQuery(filter: Filter) { +interface DittoFilter extends Filter { + local?: boolean; +} + +function getFilterQuery(filter: DittoFilter) { let query = db .selectFrom('events') .select([ @@ -62,24 +66,24 @@ function getFilterQuery(filter: Filter) { 'events.created_at', 'events.sig', ]) - .orderBy('created_at', 'desc'); + .orderBy('events.created_at', 'desc'); for (const key of Object.keys(filter)) { - switch (key as keyof Filter) { + switch (key as keyof DittoFilter) { case 'ids': - query = query.where('id', 'in', filter.ids!); + query = query.where('events.id', 'in', filter.ids!); break; case 'kinds': - query = query.where('kind', 'in', filter.kinds!); + query = query.where('events.kind', 'in', filter.kinds!); break; case 'authors': - query = query.where('pubkey', 'in', filter.authors!); + query = query.where('events.pubkey', 'in', filter.authors!); break; case 'since': - query = query.where('created_at', '>=', filter.since!); + query = query.where('events.created_at', '>=', filter.since!); break; case 'until': - query = query.where('created_at', '<=', filter.until!); + query = query.where('events.created_at', '<=', filter.until!); break; case 'limit': query = query.limit(filter.limit!); @@ -89,19 +93,23 @@ function getFilterQuery(filter: Filter) { if (key.startsWith('#')) { const tag = key.replace(/^#/, ''); const value = filter[key as `#${string}`] as string[]; - return query + query = query .leftJoin('tags', 'tags.event_id', 'events.id') .where('tags.tag', '=', tag) .where('tags.value_1', 'in', value) as typeof query; } } + if (filter.local) { + query = query.innerJoin('users', 'users.pubkey', 'events.pubkey'); + } + return query; } -async function getFilters(filters: [Filter]): Promise[]>; -async function getFilters(filters: Filter[]): Promise; -async function getFilters(filters: Filter[]) { +async function getFilters(filters: [DittoFilter]): Promise[]>; +async function getFilters(filters: DittoFilter[]): Promise; +async function getFilters(filters: DittoFilter[]) { const queries = filters .map(getFilterQuery) .map((query) => query.execute()); @@ -113,17 +121,20 @@ async function getFilters(filters: Filter[]) { )); } -function getFilter(filter: Filter): Promise[]> { +function getFilter(filter: DittoFilter): Promise[]> { return getFilters([filter]); } /** Returns whether the pubkey is followed by a local user. */ async function isLocallyFollowed(pubkey: string): Promise { - const event = await getFilterQuery({ kinds: [3], '#p': [pubkey], limit: 1 }) - .innerJoin('users', 'users.pubkey', 'events.pubkey') - .executeTakeFirst(); - - return !!event; + return Boolean( + await getFilterQuery({ + kinds: [3], + '#p': [pubkey], + limit: 1, + local: true, + }).executeTakeFirst(), + ); } export { getFilter, getFilters, insertEvent, isLocallyFollowed };