From 870a6f526157e8084cf387b8be8b57a3536ae4e3 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 17 Aug 2023 13:12:24 -0500 Subject: [PATCH 1/9] Add queries module for getting events for certain application needs --- src/client.ts | 90 +-------------------------- src/controllers/activitypub/actor.ts | 2 +- src/controllers/api/accounts.ts | 3 +- src/controllers/api/statuses.ts | 3 +- src/controllers/api/timelines.ts | 2 +- src/queries.ts | 72 +++++++++++++++++++++ src/transformers/nostr-to-mastoapi.ts | 2 +- src/utils.ts | 2 +- 8 files changed, 83 insertions(+), 93 deletions(-) create mode 100644 src/queries.ts diff --git a/src/client.ts b/src/client.ts index 38a6b226..abb5fdce 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,11 +1,9 @@ import { Conf } from '@/config.ts'; -import { Author, type Event, type Filter, findReplyTag, matchFilters, RelayPool, TTLCache } from '@/deps.ts'; -import { eventDateComparator, type PaginationParams, Time } from '@/utils.ts'; +import { type Event, type Filter, matchFilters, RelayPool, TTLCache } from '@/deps.ts'; +import { Time } from '@/utils.ts'; import type { GetFiltersOpts } from '@/types.ts'; -const db = await Deno.openKv(); - type Pool = InstanceType; /** HACK: Websockets in Deno are finnicky... get a new pool every 30 minutes. */ @@ -72,88 +70,6 @@ function getFilters(filters: Filter[], opts: GetFiltersOpts }); } -/** Get a Nostr event by its ID. */ -const getEvent = async (id: string, kind?: K): Promise | undefined> => { - const event = await (getPool().getEventById(id, Conf.poolRelays, 0) as Promise); - if (event) { - if (event.id !== id) return undefined; - if (kind && event.kind !== kind) return undefined; - return event as Event; - } -}; - -/** Get a Nostr `set_medatadata` event for a user's pubkey. */ -const getAuthor = async (pubkey: string, timeout = 1000): Promise | undefined> => { - const author = new Author(getPool(), Conf.poolRelays, pubkey); - - const event: Event<0> | null = await new Promise((resolve) => { - setTimeout(resolve, timeout, null); - return author.metaData(resolve, 0); - }); - - return event?.pubkey === pubkey ? event : undefined; -}; - -/** Get users the given pubkey follows. */ -const getFollows = async (pubkey: string): Promise | undefined> => { - const [event] = await getFilters([{ authors: [pubkey], kinds: [3] }], { timeout: 5000 }); - - // TODO: figure out a better, more generic & flexible way to handle event cache (and timeouts?) - // Prewarm cache in GET `/api/v1/accounts/verify_credentials` - if (event) { - await db.set(['event3', pubkey], event); - return event; - } else { - return (await db.get>(['event3', pubkey])).value || undefined; - } -}; - -/** Get events from people the user follows. */ -async function getFeed(event3: Event<3>, params: PaginationParams): Promise[]> { - const authors = event3.tags - .filter((tag) => tag[0] === 'p') - .map((tag) => tag[1]); - - authors.push(event3.pubkey); // see own events in feed - - const filter: Filter = { - authors, - kinds: [1], - ...params, - }; - - const results = await getFilters([filter], { timeout: 5000 }) as Event<1>[]; - return results.sort(eventDateComparator); -} - -/** Get a feed of all known text notes. */ -async function getPublicFeed(params: PaginationParams): Promise[]> { - const results = await getFilters([{ kinds: [1], ...params }], { timeout: 5000 }); - return results.sort(eventDateComparator); -} - -async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise[]> { - if (result.length < 100) { - const replyTag = findReplyTag(event); - const inReplyTo = replyTag ? replyTag[1] : undefined; - - if (inReplyTo) { - const parentEvent = await getEvent(inReplyTo, 1); - - if (parentEvent) { - result.push(parentEvent); - return getAncestors(parentEvent, result); - } - } - } - - return result.reverse(); -} - -function getDescendants(eventId: string): Promise[]> { - return getFilters([{ kinds: [1], '#e': [eventId] }], { limit: 200, timeout: 2000 }) as Promise[]>; -} - /** Publish an event to the Nostr relay. */ function publish(event: Event, relays = Conf.publishRelays): void { console.log('Publishing event', event, relays); @@ -164,4 +80,4 @@ function publish(event: Event, relays = Conf.publishRelays): void { } } -export { getAncestors, getAuthor, getDescendants, getEvent, getFeed, getFilters, getFollows, getPublicFeed, publish }; +export { getFilters, publish }; diff --git a/src/controllers/activitypub/actor.ts b/src/controllers/activitypub/actor.ts index d3547ac7..549f08d1 100644 --- a/src/controllers/activitypub/actor.ts +++ b/src/controllers/activitypub/actor.ts @@ -1,5 +1,5 @@ -import { getAuthor } from '@/client.ts'; import { findUser } from '@/db/users.ts'; +import { getAuthor } from '@/queries.ts'; import { toActor } from '@/transformers/nostr-to-activitypub.ts'; import { activityJson } from '@/utils.ts'; diff --git a/src/controllers/api/accounts.ts b/src/controllers/api/accounts.ts index d65c9e1e..0952141b 100644 --- a/src/controllers/api/accounts.ts +++ b/src/controllers/api/accounts.ts @@ -1,7 +1,8 @@ import { type AppController } from '@/app.ts'; import { type Filter, findReplyTag, z } from '@/deps.ts'; -import { getAuthor, getFollows, publish } from '@/client.ts'; +import { publish } from '@/client.ts'; import { getFilters } from '@/mixer.ts'; +import { getAuthor, getFollows } from '@/queries.ts'; import { jsonMetaContentSchema } from '@/schemas/nostr.ts'; import { signEvent } from '@/sign.ts'; import { toAccount, toStatus } from '@/transformers/nostr-to-mastoapi.ts'; diff --git a/src/controllers/api/statuses.ts b/src/controllers/api/statuses.ts index 90d3be24..03e22355 100644 --- a/src/controllers/api/statuses.ts +++ b/src/controllers/api/statuses.ts @@ -1,6 +1,7 @@ import { type AppController } from '@/app.ts'; -import { getAncestors, getDescendants, getEvent, publish } from '@/client.ts'; +import { publish } from '@/client.ts'; import { type Event, ISO6391, Kind, z } from '@/deps.ts'; +import { getAncestors, getDescendants, getEvent } from '@/queries.ts'; import { signEvent } from '@/sign.ts'; import { toStatus } from '@/transformers/nostr-to-mastoapi.ts'; import { nostrNow, parseBody } from '@/utils.ts'; diff --git a/src/controllers/api/timelines.ts b/src/controllers/api/timelines.ts index 260ee598..5b5fdcdb 100644 --- a/src/controllers/api/timelines.ts +++ b/src/controllers/api/timelines.ts @@ -1,4 +1,4 @@ -import { getFeed, getFollows, getPublicFeed } from '@/client.ts'; +import { getFeed, getFollows, getPublicFeed } from '@/queries.ts'; import { toStatus } from '@/transformers/nostr-to-mastoapi.ts'; import { buildLinkHeader, paginationSchema } from '@/utils.ts'; diff --git a/src/queries.ts b/src/queries.ts new file mode 100644 index 00000000..0c8cb86c --- /dev/null +++ b/src/queries.ts @@ -0,0 +1,72 @@ +import { type Event, type Filter, findReplyTag } from '@/deps.ts'; +import { eventDateComparator, type PaginationParams } from '@/utils.ts'; + +import { getFilters as getFiltersMixer } from './mixer.ts'; + +/** Get a Nostr event by its ID. */ +const getEvent = async (id: string, kind?: K): Promise | undefined> => { + const filter: Filter = { ids: [id], limit: 1 }; + if (kind) filter.kinds = [kind]; + const [event] = await getFiltersMixer([filter], { limit: 1, timeout: 1000 }); + return event; +}; + +/** Get a Nostr `set_medatadata` event for a user's pubkey. */ +const getAuthor = async (pubkey: string, timeout = 1000): Promise | undefined> => { + const [event] = await getFiltersMixer([{ authors: [pubkey], kinds: [0] }], { timeout }); + return event; +}; + +/** Get users the given pubkey follows. */ +const getFollows = async (pubkey: string): Promise | undefined> => { + const [event] = await getFiltersMixer([{ authors: [pubkey], kinds: [3] }], { timeout: 5000 }); + return event; +}; + +/** Get events from people the user follows. */ +async function getFeed(event3: Event<3>, params: PaginationParams): Promise[]> { + const authors = event3.tags + .filter((tag) => tag[0] === 'p') + .map((tag) => tag[1]); + + authors.push(event3.pubkey); // see own events in feed + + const filter: Filter = { + authors, + kinds: [1], + ...params, + }; + + const results = await getFiltersMixer([filter], { timeout: 5000 }) as Event<1>[]; + return results.sort(eventDateComparator); +} + +/** Get a feed of all known text notes. */ +async function getPublicFeed(params: PaginationParams): Promise[]> { + const results = await getFiltersMixer([{ kinds: [1], ...params }], { timeout: 5000 }); + return results.sort(eventDateComparator); +} + +async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise[]> { + if (result.length < 100) { + const replyTag = findReplyTag(event); + const inReplyTo = replyTag ? replyTag[1] : undefined; + + if (inReplyTo) { + const parentEvent = await getEvent(inReplyTo, 1); + + if (parentEvent) { + result.push(parentEvent); + return getAncestors(parentEvent, result); + } + } + } + + return result.reverse(); +} + +function getDescendants(eventId: string): Promise[]> { + return getFiltersMixer([{ kinds: [1], '#e': [eventId] }], { limit: 200, timeout: 2000 }) as Promise[]>; +} + +export { getAncestors, getAuthor, getDescendants, getEvent, getFeed, getFollows, getPublicFeed }; diff --git a/src/transformers/nostr-to-mastoapi.ts b/src/transformers/nostr-to-mastoapi.ts index 54f1b2e6..520246ff 100644 --- a/src/transformers/nostr-to-mastoapi.ts +++ b/src/transformers/nostr-to-mastoapi.ts @@ -1,10 +1,10 @@ import { isCWTag } from 'https://gitlab.com/soapbox-pub/mostr/-/raw/c67064aee5ade5e01597c6d23e22e53c628ef0e2/src/nostr/tags.ts'; -import { getAuthor } from '@/client.ts'; import { Conf } from '@/config.ts'; import { type Event, findReplyTag, lodash, nip19, sanitizeHtml, TTLCache, unfurl, z } from '@/deps.ts'; import { verifyNip05Cached } from '@/nip05.ts'; import { getMediaLinks, type MediaLink, parseNoteContent } from '@/note.ts'; +import { getAuthor } from '@/queries.ts'; import { emojiTagSchema, filteredArray } from '@/schema.ts'; import { jsonMetaContentSchema } from '@/schemas/nostr.ts'; import { type Nip05, nostrDate, parseNip05, Time } from '@/utils.ts'; diff --git a/src/utils.ts b/src/utils.ts index face71dc..30759140 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,7 +1,7 @@ -import { getAuthor } from '@/client.ts'; import { Conf } from '@/config.ts'; import { type Context, type Event, nip19, parseFormData, z } from '@/deps.ts'; import { lookupNip05Cached } from '@/nip05.ts'; +import { getAuthor } from '@/queries.ts'; /** Get the current time in Nostr format. */ const nostrNow = () => Math.floor(new Date().getTime() / 1000); From 5a27d791e3cbf37dca06026cb37376d1bc322618 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 17 Aug 2023 13:15:47 -0500 Subject: [PATCH 2/9] queries: make getFeed accept a pubkey instead of event3 --- src/controllers/api/timelines.ts | 9 ++------- src/queries.ts | 5 ++++- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/controllers/api/timelines.ts b/src/controllers/api/timelines.ts index 5b5fdcdb..82e1cf38 100644 --- a/src/controllers/api/timelines.ts +++ b/src/controllers/api/timelines.ts @@ -1,4 +1,4 @@ -import { getFeed, getFollows, getPublicFeed } from '@/queries.ts'; +import { getFeed, getPublicFeed } from '@/queries.ts'; import { toStatus } from '@/transformers/nostr-to-mastoapi.ts'; import { buildLinkHeader, paginationSchema } from '@/utils.ts'; @@ -8,12 +8,7 @@ const homeController: AppController = async (c) => { const params = paginationSchema.parse(c.req.query()); const pubkey = c.get('pubkey')!; - const follows = await getFollows(pubkey); - if (!follows) { - return c.json([]); - } - - const events = await getFeed(follows, params); + const events = await getFeed(pubkey, params); if (!events.length) { return c.json([]); } diff --git a/src/queries.ts b/src/queries.ts index 0c8cb86c..0734d981 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -24,7 +24,10 @@ const getFollows = async (pubkey: string): Promise | undefined> => { }; /** Get events from people the user follows. */ -async function getFeed(event3: Event<3>, params: PaginationParams): Promise[]> { +async function getFeed(pubkey: string, params: PaginationParams): Promise[]> { + const event3 = await getFollows(pubkey); + if (!event3) return []; + const authors = event3.tags .filter((tag) => tag[0] === 'p') .map((tag) => tag[1]); From c516f007a54495cef1af92403d64dc0077c72e93 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 17 Aug 2023 13:18:46 -0500 Subject: [PATCH 3/9] queries: remove unnecessary "as Event" assertions --- src/queries.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/queries.ts b/src/queries.ts index 0734d981..633f9eea 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -34,13 +34,13 @@ async function getFeed(pubkey: string, params: PaginationParams): Promise = { authors, kinds: [1], ...params, }; - const results = await getFiltersMixer([filter], { timeout: 5000 }) as Event<1>[]; + const results = await getFiltersMixer([filter], { timeout: 5000 }); return results.sort(eventDateComparator); } @@ -69,7 +69,7 @@ async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise } function getDescendants(eventId: string): Promise[]> { - return getFiltersMixer([{ kinds: [1], '#e': [eventId] }], { limit: 200, timeout: 2000 }) as Promise[]>; + return getFiltersMixer([{ kinds: [1], '#e': [eventId] }], { limit: 200, timeout: 2000 }); } export { getAncestors, getAuthor, getDescendants, getEvent, getFeed, getFollows, getPublicFeed }; From 054a399f23b7d9a4169f74bc38b8d13f9a51bb99 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 17 Aug 2023 13:19:36 -0500 Subject: [PATCH 4/9] queries: reduce getFollows timeout to 1s --- src/queries.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/queries.ts b/src/queries.ts index 633f9eea..2012c189 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -18,8 +18,8 @@ const getAuthor = async (pubkey: string, timeout = 1000): Promise | und }; /** Get users the given pubkey follows. */ -const getFollows = async (pubkey: string): Promise | undefined> => { - const [event] = await getFiltersMixer([{ authors: [pubkey], kinds: [3] }], { timeout: 5000 }); +const getFollows = async (pubkey: string, timeout = 1000): Promise | undefined> => { + const [event] = await getFiltersMixer([{ authors: [pubkey], kinds: [3] }], { timeout }); return event; }; From 96a2c8b68a813cd6e544bccabc357eb01bdbea28 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 17 Aug 2023 13:20:25 -0500 Subject: [PATCH 5/9] Remove Deno.Kv, remove --unstable flag --- .vscode/settings.json | 1 - deno.json | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4a47bd52..23baa765 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,6 @@ { "deno.enable": true, "deno.lint": true, - "deno.unstable": true, "editor.defaultFormatter": "denoland.vscode-deno", "path-intellisense.extensionOnImport": true } \ No newline at end of file diff --git a/deno.json b/deno.json index 66b12132..a2faa60b 100644 --- a/deno.json +++ b/deno.json @@ -2,12 +2,12 @@ "$schema": "https://deno.land/x/deno@v1.32.3/cli/schemas/config-file.v1.json", "lock": false, "tasks": { - "start": "deno run --allow-read --allow-write=data --allow-env --allow-net --unstable src/server.ts", - "dev": "deno run --allow-read --allow-write=data --allow-env --allow-net --unstable --watch src/server.ts", - "debug": "deno run --allow-read --allow-write=data --allow-env --allow-net --unstable --inspect src/server.ts", - "test": "DB_PATH=\":memory:\" deno test --allow-read --allow-write=data --allow-env --unstable src", - "check": "deno check --unstable src/server.ts", - "relays:sync": "deno run -A --unstable scripts/relays.ts sync", + "start": "deno run --allow-read --allow-write=data --allow-env --allow-net src/server.ts", + "dev": "deno run --allow-read --allow-write=data --allow-env --allow-net --watch src/server.ts", + "debug": "deno run --allow-read --allow-write=data --allow-env --allow-net --inspect src/server.ts", + "test": "DB_PATH=\":memory:\" deno test --allow-read --allow-write=data --allow-env src", + "check": "deno check src/server.ts", + "relays:sync": "deno run -A scripts/relays.ts sync" }, "imports": { "@/": "./src/", From 7330cd10e2ce49ae2ceefa5730cde255e0472b36 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 17 Aug 2023 14:51:27 -0500 Subject: [PATCH 6/9] Refactor getEvent to take an opts object --- src/controllers/api/statuses.ts | 6 +++--- src/queries.ts | 21 +++++++++++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/controllers/api/statuses.ts b/src/controllers/api/statuses.ts index 03e22355..121f6dba 100644 --- a/src/controllers/api/statuses.ts +++ b/src/controllers/api/statuses.ts @@ -29,7 +29,7 @@ const createStatusSchema = z.object({ const statusController: AppController = async (c) => { const id = c.req.param('id'); - const event = await getEvent(id, 1); + const event = await getEvent(id, { kind: 1 }); if (event) { return c.json(await toStatus(event as Event<1>)); } @@ -88,7 +88,7 @@ const createStatusController: AppController = async (c) => { const contextController: AppController = async (c) => { const id = c.req.param('id'); - const event = await getEvent(id, 1); + const event = await getEvent(id, { kind: 1 }); if (event) { const ancestorEvents = await getAncestors(event); @@ -105,7 +105,7 @@ const contextController: AppController = async (c) => { const favouriteController: AppController = async (c) => { const id = c.req.param('id'); - const target = await getEvent(id, 1); + const target = await getEvent(id, { kind: 1 }); if (target) { const event = await signEvent({ diff --git a/src/queries.ts b/src/queries.ts index 2012c189..208fc616 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -3,11 +3,24 @@ import { eventDateComparator, type PaginationParams } from '@/utils.ts'; import { getFilters as getFiltersMixer } from './mixer.ts'; +interface GetEventOpts { + /** Timeout in milliseconds. */ + timeout?: number; + /** Event kind. */ + kind?: K; +} + /** Get a Nostr event by its ID. */ -const getEvent = async (id: string, kind?: K): Promise | undefined> => { +const getEvent = async ( + id: string, + opts: GetEventOpts = {}, +): Promise | undefined> => { + const { kind, timeout = 1000 } = opts; const filter: Filter = { ids: [id], limit: 1 }; - if (kind) filter.kinds = [kind]; - const [event] = await getFiltersMixer([filter], { limit: 1, timeout: 1000 }); + if (kind) { + filter.kinds = [kind]; + } + const [event] = await getFiltersMixer([filter], { limit: 1, timeout }); return event; }; @@ -56,7 +69,7 @@ async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise const inReplyTo = replyTag ? replyTag[1] : undefined; if (inReplyTo) { - const parentEvent = await getEvent(inReplyTo, 1); + const parentEvent = await getEvent(inReplyTo, { kind: 1 }); if (parentEvent) { result.push(parentEvent); From 4f37a1b9f898bff5f35a11dbd18ce39ebf2655c6 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 17 Aug 2023 14:55:00 -0500 Subject: [PATCH 7/9] queries: don't unnecessarily sort things --- src/queries.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/queries.ts b/src/queries.ts index 208fc616..fd41c6ae 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -1,5 +1,5 @@ import { type Event, type Filter, findReplyTag } from '@/deps.ts'; -import { eventDateComparator, type PaginationParams } from '@/utils.ts'; +import { type PaginationParams } from '@/utils.ts'; import { getFilters as getFiltersMixer } from './mixer.ts'; @@ -53,14 +53,12 @@ async function getFeed(pubkey: string, params: PaginationParams): Promise[]> { - const results = await getFiltersMixer([{ kinds: [1], ...params }], { timeout: 5000 }); - return results.sort(eventDateComparator); +function getPublicFeed(params: PaginationParams): Promise[]> { + return getFiltersMixer([{ kinds: [1], ...params }], { timeout: 5000 }); } async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise[]> { From 4f9b5c1431060f3dfdc62fdf0ce0bdbae295070c Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 17 Aug 2023 14:57:46 -0500 Subject: [PATCH 8/9] statusController: remove unnecessary "as Event" --- src/controllers/api/statuses.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/api/statuses.ts b/src/controllers/api/statuses.ts index 121f6dba..2f594ac7 100644 --- a/src/controllers/api/statuses.ts +++ b/src/controllers/api/statuses.ts @@ -1,6 +1,6 @@ import { type AppController } from '@/app.ts'; import { publish } from '@/client.ts'; -import { type Event, ISO6391, Kind, z } from '@/deps.ts'; +import { ISO6391, Kind, z } from '@/deps.ts'; import { getAncestors, getDescendants, getEvent } from '@/queries.ts'; import { signEvent } from '@/sign.ts'; import { toStatus } from '@/transformers/nostr-to-mastoapi.ts'; @@ -31,7 +31,7 @@ const statusController: AppController = async (c) => { const event = await getEvent(id, { kind: 1 }); if (event) { - return c.json(await toStatus(event as Event<1>)); + return c.json(await toStatus(event)); } return c.json({ error: 'Event not found.' }, 404); From 299a1a0db0e2bac7e03fa671d6ea74094423a2bc Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 17 Aug 2023 15:41:27 -0500 Subject: [PATCH 9/9] Refactor some code that uses getFilters to import the whole module under a namespace --- src/controllers/api/accounts.ts | 4 ++-- src/controllers/nostr/relay.ts | 6 +++--- src/mixer.ts | 8 ++++---- src/queries.ts | 14 +++++++------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/controllers/api/accounts.ts b/src/controllers/api/accounts.ts index 0952141b..544447b2 100644 --- a/src/controllers/api/accounts.ts +++ b/src/controllers/api/accounts.ts @@ -1,7 +1,7 @@ import { type AppController } from '@/app.ts'; import { type Filter, findReplyTag, z } from '@/deps.ts'; import { publish } from '@/client.ts'; -import { getFilters } from '@/mixer.ts'; +import * as mixer from '@/mixer.ts'; import { getAuthor, getFollows } from '@/queries.ts'; import { jsonMetaContentSchema } from '@/schemas/nostr.ts'; import { signEvent } from '@/sign.ts'; @@ -117,7 +117,7 @@ const accountStatusesController: AppController = async (c) => { filter['#t'] = [tagged]; } - let events = await getFilters([filter]); + let events = await mixer.getFilters([filter]); events.sort(eventDateComparator); if (exclude_replies) { diff --git a/src/controllers/nostr/relay.ts b/src/controllers/nostr/relay.ts index b4d91d16..24316e7c 100644 --- a/src/controllers/nostr/relay.ts +++ b/src/controllers/nostr/relay.ts @@ -1,4 +1,4 @@ -import { getFilters, insertEvent } from '@/db/events.ts'; +import * as eventsDB from '@/db/events.ts'; import { findUser } from '@/db/users.ts'; import { jsonSchema } from '@/schema.ts'; import { @@ -46,7 +46,7 @@ function connectStream(socket: WebSocket) { } async function handleReq([_, sub, ...filters]: ClientREQ) { - for (const event of await getFilters(prepareFilters(filters))) { + for (const event of await eventsDB.getFilters(prepareFilters(filters))) { send(['EVENT', sub, event]); } send(['EOSE', sub]); @@ -54,7 +54,7 @@ function connectStream(socket: WebSocket) { async function handleEvent([_, event]: ClientEVENT) { if (await findUser({ pubkey: event.pubkey })) { - insertEvent(event); + eventsDB.insertEvent(event); send(['OK', event.id, true, '']); } else { send(['OK', event.id, false, 'blocked: only registered users can post']); diff --git a/src/mixer.ts b/src/mixer.ts index 82b8ba99..aed5311f 100644 --- a/src/mixer.ts +++ b/src/mixer.ts @@ -1,7 +1,7 @@ import { type Event, matchFilters } from '@/deps.ts'; -import { getFilters as getFiltersClient } from '@/client.ts'; -import { getFilters as getFiltersDB } from '@/db/events.ts'; +import * as client from '@/client.ts'; +import * as eventsDB from '@/db/events.ts'; import { eventDateComparator } from '@/utils.ts'; import type { DittoFilter, GetFiltersOpts } from '@/types.ts'; @@ -12,8 +12,8 @@ async function getFilters( opts?: GetFiltersOpts, ): Promise[]> { const results = await Promise.allSettled([ - getFiltersClient(filters, opts), - getFiltersDB(filters, opts), + client.getFilters(filters, opts), + eventsDB.getFilters(filters, opts), ]); const events = results diff --git a/src/queries.ts b/src/queries.ts index fd41c6ae..7d03c308 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -1,7 +1,7 @@ import { type Event, type Filter, findReplyTag } from '@/deps.ts'; import { type PaginationParams } from '@/utils.ts'; -import { getFilters as getFiltersMixer } from './mixer.ts'; +import * as mixer from './mixer.ts'; interface GetEventOpts { /** Timeout in milliseconds. */ @@ -20,19 +20,19 @@ const getEvent = async ( if (kind) { filter.kinds = [kind]; } - const [event] = await getFiltersMixer([filter], { limit: 1, timeout }); + const [event] = await mixer.getFilters([filter], { limit: 1, timeout }); return event; }; /** Get a Nostr `set_medatadata` event for a user's pubkey. */ const getAuthor = async (pubkey: string, timeout = 1000): Promise | undefined> => { - const [event] = await getFiltersMixer([{ authors: [pubkey], kinds: [0] }], { timeout }); + const [event] = await mixer.getFilters([{ authors: [pubkey], kinds: [0] }], { timeout }); return event; }; /** Get users the given pubkey follows. */ const getFollows = async (pubkey: string, timeout = 1000): Promise | undefined> => { - const [event] = await getFiltersMixer([{ authors: [pubkey], kinds: [3] }], { timeout }); + const [event] = await mixer.getFilters([{ authors: [pubkey], kinds: [3] }], { timeout }); return event; }; @@ -53,12 +53,12 @@ async function getFeed(pubkey: string, params: PaginationParams): Promise[]> { - return getFiltersMixer([{ kinds: [1], ...params }], { timeout: 5000 }); + return mixer.getFilters([{ kinds: [1], ...params }], { timeout: 5000 }); } async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise[]> { @@ -80,7 +80,7 @@ async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise } function getDescendants(eventId: string): Promise[]> { - return getFiltersMixer([{ kinds: [1], '#e': [eventId] }], { limit: 200, timeout: 2000 }); + return mixer.getFilters([{ kinds: [1], '#e': [eventId] }], { limit: 200, timeout: 2000 }); } export { getAncestors, getAuthor, getDescendants, getEvent, getFeed, getFollows, getPublicFeed };