From ccb8c534ca7005dd02e22c7c64a136978c9d4f98 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 28 Aug 2023 19:51:21 -0500 Subject: [PATCH] Add hashtag timeline --- src/app.ts | 3 ++- src/controllers/api/timelines.ts | 23 ++++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/app.ts b/src/app.ts index ccf36e8..6d2305e 100644 --- a/src/app.ts +++ b/src/app.ts @@ -38,7 +38,7 @@ import { statusController, } from './controllers/api/statuses.ts'; import { streamingController } from './controllers/api/streaming.ts'; -import { homeController, publicController } from './controllers/api/timelines.ts'; +import { hashtagTimelineController, homeController, publicController } from './controllers/api/timelines.ts'; import { trendingTagsController } from './controllers/api/trends.ts'; import { indexController } from './controllers/site.ts'; import { hostMetaController } from './controllers/well-known/host-meta.ts'; @@ -109,6 +109,7 @@ app.post('/api/v1/statuses', requirePubkey, createStatusController); app.get('/api/v1/timelines/home', requirePubkey, homeController); app.get('/api/v1/timelines/public', publicController); +app.get('/api/v1/timelines/tag/:hashtag', hashtagTimelineController); app.get('/api/v1/preferences', preferencesController); app.get('/api/v1/search', searchController); diff --git a/src/controllers/api/timelines.ts b/src/controllers/api/timelines.ts index 6470e43..801ee10 100644 --- a/src/controllers/api/timelines.ts +++ b/src/controllers/api/timelines.ts @@ -1,8 +1,10 @@ import { z } from '@/deps.ts'; +import * as mixer from '@/mixer.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/web.ts'; +import { Time } from '@/utils.ts'; import type { AppController } from '@/app.ts'; @@ -40,4 +42,23 @@ const publicController: AppController = async (c) => { return c.json(statuses, 200, link ? { link } : undefined); }; -export { homeController, publicController }; +const hashtagTimelineController: AppController = async (c) => { + const hashtag = c.req.param('hashtag')!; + const params = paginationSchema.parse(c.req.query()); + + const events = await mixer.getFilters( + [{ kinds: [1], '#t': [hashtag], ...params }], + { timeout: Time.seconds(3) }, + ); + + if (!events.length) { + return c.json([]); + } + + const statuses = (await Promise.all(events.map(toStatus))).filter(Boolean); + + const link = buildLinkHeader(c.req.url, events); + return c.json(statuses, 200, link ? { link } : undefined); +}; + +export { hashtagTimelineController, homeController, publicController };