Get rid if trending-events.ts, do everything with tag values (brave)

This commit is contained in:
Alex Gleason 2024-06-02 19:40:42 -05:00
parent 3373673706
commit c7c75a7147
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
3 changed files with 10 additions and 91 deletions

View File

@ -4,49 +4,12 @@ import { Conf } from '@/config.ts';
import { DittoDB } from '@/db/DittoDB.ts'; import { DittoDB } from '@/db/DittoDB.ts';
import { handleEvent } from '@/pipeline.ts'; import { handleEvent } from '@/pipeline.ts';
import { AdminSigner } from '@/signers/AdminSigner.ts'; import { AdminSigner } from '@/signers/AdminSigner.ts';
import { getTrendingEvents } from '@/trends/trending-events.ts';
import { getTrendingTagValues } from '@/trends/trending-tag-values.ts'; import { getTrendingTagValues } from '@/trends/trending-tag-values.ts';
import { Time } from '@/utils/time.ts'; import { Time } from '@/utils/time.ts';
const console = new Stickynotes('ditto:trends'); const console = new Stickynotes('ditto:trends');
async function updateTrendingNotes() { async function updateTrendingTags(tagName: string, kinds: number[], limit: number, extra = '', aliases?: string[]) {
console.info('Updating trending notes...');
const kysely = await DittoDB.getInstance();
const signal = AbortSignal.timeout(1000);
const yesterday = Math.floor((Date.now() - Time.days(1)) / 1000);
const now = Math.floor(Date.now() / 1000);
const events = await getTrendingEvents(kysely, {
kinds: [1],
since: yesterday,
until: now,
limit: 40,
});
if (!events.length) {
return;
}
const signer = new AdminSigner();
const label = await signer.signEvent({
kind: 1985,
content: '',
tags: [
['L', 'pub.ditto.trends'],
['l', '#e', 'pub.ditto.trends'],
...events.map(({ id }) => ['e', id, Conf.relay]),
],
created_at: Math.floor(Date.now() / 1000),
});
await handleEvent(label, signal);
console.info('Trending notes updated.');
}
async function updateTrendingTags(tagName: string, limit: number, extra = '') {
console.info(`Updating trending #${tagName}...`); console.info(`Updating trending #${tagName}...`);
const kysely = await DittoDB.getInstance(); const kysely = await DittoDB.getInstance();
const signal = AbortSignal.timeout(1000); const signal = AbortSignal.timeout(1000);
@ -54,7 +17,10 @@ async function updateTrendingTags(tagName: string, limit: number, extra = '') {
const yesterday = Math.floor((Date.now() - Time.days(1)) / 1000); const yesterday = Math.floor((Date.now() - Time.days(1)) / 1000);
const now = Math.floor(Date.now() / 1000); const now = Math.floor(Date.now() / 1000);
const trends = await getTrendingTagValues(kysely, tagName, { const tagNames = aliases ? [tagName, ...aliases] : [tagName];
const trends = await getTrendingTagValues(kysely, tagNames, {
kinds,
since: yesterday, since: yesterday,
until: now, until: now,
limit, limit,
@ -83,7 +49,7 @@ async function updateTrendingTags(tagName: string, limit: number, extra = '') {
/** Start cron jobs for the application. */ /** Start cron jobs for the application. */
export function cron() { export function cron() {
Deno.cron('update trending notes', '15 * * * *', updateTrendingNotes); Deno.cron('update trending notes', '15 * * * *', () => updateTrendingTags('e', [1, 6, 7], 40, Conf.relay, ['q']));
Deno.cron('update trending hashtags', '30 * * * *', () => updateTrendingTags('t', 20)); Deno.cron('update trending hashtags', '30 * * * *', () => updateTrendingTags('t', [1], 20));
Deno.cron('update trending links', '45 * * * *', () => updateTrendingTags('r', 20)); Deno.cron('update trending links', '45 * * * *', () => updateTrendingTags('r', [1], 20));
} }

View File

@ -1,47 +0,0 @@
import { NostrEvent, NostrFilter } from '@nostrify/nostrify';
import { Kysely, sql } from 'kysely';
import { DittoTables } from '@/db/DittoTables.ts';
/**
* Make a direct query to the database to get trending events within the specified timeframe.
* Trending events are determined by the number of reposts, replies, and reactions.
*
* This query makes use of cached stats (in the `event_stats` table).
* The query is SLOW so it needs to be run on a schedule and cached.
*/
export async function getTrendingEvents(
/** Kysely instance to execute queries on. */
kysely: Kysely<DittoTables>,
/** Filter of eligible events. */
filter: NostrFilter,
): Promise<NostrEvent[]> {
let query = kysely
.selectFrom('nostr_events')
.selectAll('nostr_events')
.innerJoin('event_stats', 'event_stats.event_id', 'nostr_events.id')
.orderBy(
sql`(event_stats.reposts_count * 2) + (event_stats.replies_count) + (event_stats.reactions_count)`,
'desc',
);
if (filter.kinds) {
query = query.where('nostr_events.kind', 'in', filter.kinds);
}
if (typeof filter.since === 'number') {
query = query.where('nostr_events.created_at', '>=', filter.since);
}
if (typeof filter.until === 'number') {
query = query.where('nostr_events.created_at', '<=', filter.until);
}
if (typeof filter.limit === 'number') {
query = query.limit(filter.limit);
}
const rows = await query.execute();
return rows.map((row) => ({
...row,
tags: JSON.parse(row.tags),
}));
}

View File

@ -8,7 +8,7 @@ export async function getTrendingTagValues(
/** Kysely instance to execute queries on. */ /** Kysely instance to execute queries on. */
kysely: Kysely<DittoTables>, kysely: Kysely<DittoTables>,
/** Tag name to filter by, eg `t` or `r`. */ /** Tag name to filter by, eg `t` or `r`. */
tagName: string, tagNames: string[],
/** Filter of eligible events. */ /** Filter of eligible events. */
filter: NostrFilter, filter: NostrFilter,
): Promise<{ value: string; authors: number; uses: number }[]> { ): Promise<{ value: string; authors: number; uses: number }[]> {
@ -20,7 +20,7 @@ export async function getTrendingTagValues(
fn.agg<number>('count', ['nostr_events.pubkey']).distinct().as('authors'), fn.agg<number>('count', ['nostr_events.pubkey']).distinct().as('authors'),
fn.countAll<number>().as('uses'), fn.countAll<number>().as('uses'),
]) ])
.where('nostr_tags.name', '=', tagName) .where('nostr_tags.name', 'in', tagNames)
.groupBy('nostr_tags.value') .groupBy('nostr_tags.value')
.orderBy((c) => c.fn.agg('count', ['nostr_events.pubkey']).distinct(), 'desc'); .orderBy((c) => c.fn.agg('count', ['nostr_events.pubkey']).distinct(), 'desc');