Fix tag order

This commit is contained in:
Alex Gleason 2024-06-02 19:02:31 -05:00
parent fc11e34499
commit 133a684d32
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
2 changed files with 90 additions and 51 deletions

View File

@ -1,7 +1,7 @@
import { NostrEvent } from '@nostrify/nostrify'; import { NostrEvent, NStore } from '@nostrify/nostrify';
import { z } from 'zod'; import { z } from 'zod';
import { type AppController } from '@/app.ts'; import { AppController } from '@/app.ts';
import { Conf } from '@/config.ts'; 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';
@ -10,7 +10,7 @@ import { renderStatus } from '@/views/mastodon/statuses.ts';
let trendingHashtagsCache = getTrendingHashtags(); let trendingHashtagsCache = getTrendingHashtags();
Deno.cron('update trends cache', { minute: { every: 15 } }, async () => { Deno.cron('update trending hashtags cache', { minute: { every: 15 } }, async () => {
const trends = await getTrendingHashtags(); const trends = await getTrendingHashtags();
trendingHashtagsCache = Promise.resolve(trends); trendingHashtagsCache = Promise.resolve(trends);
}); });
@ -28,61 +28,23 @@ const trendingTagsController: AppController = async (c) => {
async function getTrendingHashtags() { async function getTrendingHashtags() {
const store = await Storages.db(); const store = await Storages.db();
const trends = await getTrendingTags(store, 't');
const [label] = await store.query([{ return trends.map((trend) => {
kinds: [1985], const hashtag = trend.value;
'#L': ['pub.ditto.trends'],
'#l': ['#t'],
authors: [Conf.pubkey],
limit: 1,
}]);
if (!label) { const history = trend.history.map(({ day, authors, uses }) => ({
return []; day: String(day),
} accounts: String(authors),
uses: String(uses),
const tags = label.tags.filter(([name]) => name === 't');
const now = new Date();
const lastWeek = new Date(now.getTime() - Time.days(7));
const dates = generateDateRange(lastWeek, now);
return Promise.all(tags.map(async ([_, hashtag]) => {
const filters = dates.map((date) => ({
kinds: [1985],
'#L': ['pub.ditto.trends'],
'#l': ['#t'],
'#t': [hashtag],
authors: [Conf.pubkey],
since: Math.floor(date.getTime() / 1000),
until: Math.floor((date.getTime() + Time.days(1)) / 1000),
limit: 1,
})); }));
const labels = await store.query(filters);
const history = dates.map((date) => {
const label = labels.find((label) => {
const since = Math.floor(date.getTime() / 1000);
const until = Math.floor((date.getTime() + Time.days(1)) / 1000);
return label.created_at >= since && label.created_at < until;
});
const [, , , accounts, uses] = label?.tags.find(([name, value]) => name === 't' && value === hashtag) ?? [];
return {
day: String(date.getTime() / 1000),
accounts: accounts || '0',
uses: uses || '0',
};
});
return { return {
name: hashtag, name: hashtag,
url: Conf.local(`/tags/${hashtag}`), url: Conf.local(`/tags/${hashtag}`),
history, history,
}; };
})); });
} }
const trendingStatusesQuerySchema = z.object({ const trendingStatusesQuerySchema = z.object({
@ -126,4 +88,69 @@ const trendingStatusesController: AppController = async (c) => {
return c.json(statuses.filter(Boolean)); return c.json(statuses.filter(Boolean));
}; };
interface TrendingTag {
name: string;
value: string;
history: {
day: number;
authors: number;
uses: number;
}[];
}
export async function getTrendingTags(store: NStore, tagName: string): Promise<TrendingTag[]> {
const filter = {
kinds: [1985],
'#L': ['pub.ditto.trends'],
'#l': [`#${tagName}`],
authors: [Conf.pubkey],
limit: 1,
};
const [label] = await store.query([filter]);
if (!label) {
return [];
}
const tags = label.tags.filter(([name]) => name === tagName);
const now = new Date();
const lastWeek = new Date(now.getTime() - Time.days(7));
const dates = generateDateRange(lastWeek, now);
return Promise.all(tags.map(async ([_, value]) => {
const filters = dates.map((date) => ({
...filter,
[`#${tagName}`]: [value],
since: Math.floor(date.getTime() / 1000),
until: Math.floor((date.getTime() + Time.days(1)) / 1000),
}));
const labels = await store.query(filters);
const history = dates.map((date) => {
const label = labels.find((label) => {
const since = Math.floor(date.getTime() / 1000);
const until = Math.floor((date.getTime() + Time.days(1)) / 1000);
return label.created_at >= since && label.created_at < until;
});
const [, , , accounts, uses] = label?.tags.find((tag) => tag[0] === tagName && tag[1] === value) ?? [];
return {
day: Math.floor(date.getTime() / 1000),
authors: Number(accounts || 0),
uses: Number(uses || 0),
};
});
return {
name: tagName,
value,
history,
};
}));
}
export { trendingStatusesController, trendingTagsController }; export { trendingStatusesController, trendingTagsController };

View File

@ -25,6 +25,10 @@ async function updateTrendingNotes() {
limit: 40, limit: 40,
}); });
if (!events.length) {
return;
}
const signer = new AdminSigner(); const signer = new AdminSigner();
const label = await signer.signEvent({ const label = await signer.signEvent({
@ -56,6 +60,10 @@ async function updateTrendingHashtags() {
limit: 20, limit: 20,
}); });
if (!hashtags.length) {
return;
}
const signer = new AdminSigner(); const signer = new AdminSigner();
const label = await signer.signEvent({ const label = await signer.signEvent({
@ -64,7 +72,7 @@ async function updateTrendingHashtags() {
tags: [ tags: [
['L', 'pub.ditto.trends'], ['L', 'pub.ditto.trends'],
['l', '#t', 'pub.ditto.trends'], ['l', '#t', 'pub.ditto.trends'],
...hashtags.map(({ value, authors, uses }) => ['t', '', value, authors.toString(), uses.toString()]), ...hashtags.map(({ value, authors, uses }) => ['t', value, '', authors.toString(), uses.toString()]),
], ],
created_at: Math.floor(Date.now() / 1000), created_at: Math.floor(Date.now() / 1000),
}); });
@ -87,6 +95,10 @@ async function updateTrendingLinks() {
limit: 20, limit: 20,
}); });
if (!links.length) {
return;
}
const signer = new AdminSigner(); const signer = new AdminSigner();
const label = await signer.signEvent({ const label = await signer.signEvent({
@ -95,7 +107,7 @@ async function updateTrendingLinks() {
tags: [ tags: [
['L', 'pub.ditto.trends'], ['L', 'pub.ditto.trends'],
['l', '#r', 'pub.ditto.trends'], ['l', '#r', 'pub.ditto.trends'],
...links.map(({ value, authors, uses }) => ['r', '', value, authors.toString(), uses.toString()]), ...links.map(({ value, authors, uses }) => ['r', value, '', authors.toString(), uses.toString()]),
], ],
created_at: Math.floor(Date.now() / 1000), created_at: Math.floor(Date.now() / 1000),
}); });