From c83a2dba7e99aefac0c4cc930c4a80dd4a08bac0 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 30 Jan 2025 20:39:51 -0600 Subject: [PATCH 1/3] Give requireSigner middleware the right type --- src/middleware/requireSigner.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/middleware/requireSigner.ts b/src/middleware/requireSigner.ts index c954dbd6..e360ab42 100644 --- a/src/middleware/requireSigner.ts +++ b/src/middleware/requireSigner.ts @@ -1,9 +1,9 @@ +import { MiddlewareHandler } from '@hono/hono'; import { HTTPException } from '@hono/hono/http-exception'; - -import { AppMiddleware } from '@/app.ts'; +import { NostrSigner } from '@nostrify/nostrify'; /** Throw a 401 if a signer isn't set. */ -export const requireSigner: AppMiddleware = async (c, next) => { +export const requireSigner: MiddlewareHandler<{ Variables: { signer: NostrSigner } }> = async (c, next) => { if (!c.get('signer')) { throw new HTTPException(401, { message: 'No pubkey provided' }); } From c3403ba724f3449d3b93cd417c09e4e0b6726382 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 30 Jan 2025 21:03:42 -0600 Subject: [PATCH 2/3] Make AppController accept a path parameter --- src/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.ts b/src/app.ts index 8bdeccf3..18b0fb96 100644 --- a/src/app.ts +++ b/src/app.ts @@ -166,7 +166,7 @@ export interface AppEnv extends HonoEnv { type AppContext = Context; type AppMiddleware = MiddlewareHandler; -type AppController = Handler>; +type AppController

= Handler>; const app = new Hono({ strict: false }); From 99d52f864081dd9fd97a7fae1542ce36824c4f89 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 30 Jan 2025 21:16:38 -0600 Subject: [PATCH 3/3] Add local suggestions controller --- src/app.ts | 7 ++++++- src/controllers/api/suggestions.ts | 23 ++++++++++++++++++++++- src/utils/api.ts | 3 ++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/app.ts b/src/app.ts index 18b0fb96..6929757f 100644 --- a/src/app.ts +++ b/src/app.ts @@ -109,7 +109,11 @@ import { zappedByController, } from '@/controllers/api/statuses.ts'; import { streamingController } from '@/controllers/api/streaming.ts'; -import { suggestionsV1Controller, suggestionsV2Controller } from '@/controllers/api/suggestions.ts'; +import { + localSuggestionsController, + suggestionsV1Controller, + suggestionsV2Controller, +} from '@/controllers/api/suggestions.ts'; import { hashtagTimelineController, homeTimelineController, @@ -348,6 +352,7 @@ app.get( app.get('/api/v1/suggestions', suggestionsV1Controller); app.get('/api/v2/suggestions', suggestionsV2Controller); +app.get('/api/v2/ditto/suggestions/local', localSuggestionsController); app.get('/api/v1/notifications', rateLimitMiddleware(8, Time.seconds(30)), requireSigner, notificationsController); app.get('/api/v1/notifications/:id', requireSigner, notificationController); diff --git a/src/controllers/api/suggestions.ts b/src/controllers/api/suggestions.ts index c047c415..e2357c1a 100644 --- a/src/controllers/api/suggestions.ts +++ b/src/controllers/api/suggestions.ts @@ -4,7 +4,7 @@ import { matchFilter } from 'nostr-tools'; import { AppContext, AppController } from '@/app.ts'; import { Conf } from '@/config.ts'; import { hydrateEvents } from '@/storages/hydrate.ts'; -import { paginatedList } from '@/utils/api.ts'; +import { paginated, paginatedList } from '@/utils/api.ts'; import { getTagSet } from '@/utils/tags.ts'; import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts'; @@ -87,3 +87,24 @@ async function renderV2Suggestions(c: AppContext, params: { offset: number; limi }; })); } + +export const localSuggestionsController: AppController = async (c) => { + const signal = c.req.raw.signal; + const params = c.get('pagination'); + const store = c.get('store'); + + const events = await store.query( + [{ kinds: [0], search: `domain:${Conf.url.host}`, ...params }], + { signal }, + ) + .then((events) => hydrateEvents({ store, events, signal })); + + const suggestions = await Promise.all(events.map(async (event) => { + return { + source: 'global', + account: await renderAccount(event), + }; + })); + + return paginated(c, events, suggestions); +}; diff --git a/src/utils/api.ts b/src/utils/api.ts index 89cb608b..29304cbd 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -207,7 +207,8 @@ function buildLinkHeader(url: string, events: NostrEvent[]): string | undefined return `<${next}>; rel="next", <${prev}>; rel="prev"`; } -type Entity = { id: string }; +// deno-lint-ignore ban-types +type Entity = {}; type HeaderRecord = Record; /** Return results with pagination headers. Assumes chronological sorting of events. */