Implement trending links
This commit is contained in:
parent
9cdfc188aa
commit
4329d8ed9f
|
@ -79,7 +79,11 @@ import {
|
||||||
publicTimelineController,
|
publicTimelineController,
|
||||||
suggestedTimelineController,
|
suggestedTimelineController,
|
||||||
} from '@/controllers/api/timelines.ts';
|
} 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 { indexController } from '@/controllers/site.ts';
|
||||||
import { nodeInfoController, nodeInfoSchemaController } from '@/controllers/well-known/nodeinfo.ts';
|
import { nodeInfoController, nodeInfoSchemaController } from '@/controllers/well-known/nodeinfo.ts';
|
||||||
import { nostrController } from '@/controllers/well-known/nostr.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/pleroma/frontend_configurations', frontendConfigController);
|
||||||
|
|
||||||
app.get('/api/v1/trends/statuses', trendingStatusesController);
|
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/tags', trendingTagsController);
|
||||||
app.get('/api/v1/trends', trendingTagsController);
|
app.get('/api/v1/trends', trendingTagsController);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Conf } from '@/config.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { Storages } from '@/storages.ts';
|
import { Storages } from '@/storages.ts';
|
||||||
import { generateDateRange, Time } from '@/utils/time.ts';
|
import { generateDateRange, Time } from '@/utils/time.ts';
|
||||||
|
import { unfurlCardCached } from '@/utils/unfurl.ts';
|
||||||
import { renderStatus } from '@/views/mastodon/statuses.ts';
|
import { renderStatus } from '@/views/mastodon/statuses.ts';
|
||||||
|
|
||||||
let trendingHashtagsCache = getTrendingHashtags();
|
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({
|
const trendingStatusesQuerySchema = z.object({
|
||||||
limit: z.coerce.number().catch(20).transform((value) => Math.min(Math.max(value, 0), 40)),
|
limit: z.coerce.number().catch(20).transform((value) => Math.min(Math.max(value, 0), 40)),
|
||||||
offset: z.number().nonnegative().catch(0),
|
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 };
|
||||||
|
|
Loading…
Reference in New Issue