Merge branch 'trending-links' into 'main'

Implement trending links

See merge request soapbox-pub/ditto!352
This commit is contained in:
Alex Gleason 2024-06-03 04:27:55 +00:00
commit cf5f178e4c
2 changed files with 56 additions and 2 deletions

View File

@ -79,7 +79,11 @@ import {
publicTimelineController,
suggestedTimelineController,
} from '@/controllers/api/timelines.ts';
import { trendingStatusesController, trendingTagsController } from '@/controllers/api/trends.ts';
import {
trendingLinksController,
trendingStatusesController,
trendingTagsController,
} from '@/controllers/api/trends.ts';
import { indexController } from '@/controllers/site.ts';
import { nodeInfoController, nodeInfoSchemaController } from '@/controllers/well-known/nodeinfo.ts';
import { nostrController } from '@/controllers/well-known/nostr.ts';
@ -207,6 +211,7 @@ app.get('/api/v2/search', searchController);
app.get('/api/pleroma/frontend_configurations', frontendConfigController);
app.get('/api/v1/trends/statuses', trendingStatusesController);
app.get('/api/v1/trends/links', trendingLinksController);
app.get('/api/v1/trends/tags', trendingTagsController);
app.get('/api/v1/trends', trendingTagsController);

View File

@ -6,6 +6,7 @@ import { Conf } from '@/config.ts';
import { hydrateEvents } from '@/storages/hydrate.ts';
import { Storages } from '@/storages.ts';
import { generateDateRange, Time } from '@/utils/time.ts';
import { unfurlCardCached } from '@/utils/unfurl.ts';
import { renderStatus } from '@/views/mastodon/statuses.ts';
let trendingHashtagsCache = getTrendingHashtags();
@ -47,6 +48,54 @@ async function getTrendingHashtags() {
});
}
let trendingLinksCache = getTrendingLinks();
Deno.cron('update trending links cache', { minute: { every: 15 } }, async () => {
const trends = await getTrendingLinks();
trendingLinksCache = Promise.resolve(trends);
});
const trendingLinksController: AppController = async (c) => {
const { limit, offset } = trendingTagsQuerySchema.parse(c.req.query());
const trends = await trendingLinksCache;
return c.json(trends.slice(offset, offset + limit));
};
async function getTrendingLinks() {
const store = await Storages.db();
const trends = await getTrendingTags(store, 'r');
return Promise.all(trends.map(async (trend) => {
const link = trend.value;
const card = await unfurlCardCached(link);
const history = trend.history.map(({ day, authors, uses }) => ({
day: String(day),
accounts: String(authors),
uses: String(uses),
}));
return {
url: link,
title: '',
description: '',
type: 'link',
author_name: '',
author_url: '',
provider_name: '',
provider_url: '',
html: '',
width: 0,
height: 0,
image: null,
embed_url: '',
blurhash: null,
...card,
history,
};
}));
}
const trendingStatusesQuerySchema = z.object({
limit: z.coerce.number().catch(20).transform((value) => Math.min(Math.max(value, 0), 40)),
offset: z.number().nonnegative().catch(0),
@ -153,4 +202,4 @@ export async function getTrendingTags(store: NStore, tagName: string): Promise<T
}));
}
export { trendingStatusesController, trendingTagsController };
export { trendingLinksController, trendingStatusesController, trendingTagsController };