Get rid if trending-events.ts, do everything with tag values (brave)
This commit is contained in:
parent
3373673706
commit
c7c75a7147
50
src/cron.ts
50
src/cron.ts
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
|
||||||
}));
|
|
||||||
}
|
|
|
@ -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');
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue