Fix tag order
This commit is contained in:
parent
fc11e34499
commit
133a684d32
|
@ -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 };
|
||||||
|
|
16
src/cron.ts
16
src/cron.ts
|
@ -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),
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue