getTrendingHashtags -> getTrendingTagValues
This commit is contained in:
parent
b5545ddb60
commit
cd46d63999
21
src/cron.ts
21
src/cron.ts
|
@ -1,11 +1,11 @@
|
|||
import { Stickynotes } from '@soapbox/stickynotes';
|
||||
|
||||
import { DittoDB } from '@/db/DittoDB.ts';
|
||||
import { getTrendingEvents } from '@/trends/trending-events.ts';
|
||||
import { Time } from '@/utils/time.ts';
|
||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||
import { handleEvent } from '@/pipeline.ts';
|
||||
import { getTrendingHashtags } from '@/trends/trending-hashtags.ts';
|
||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||
import { getTrendingEvents } from '@/trends/trending-events.ts';
|
||||
import { getTrendingTagValues } from '@/trends/trending-tag-values.ts';
|
||||
import { Time } from '@/utils/time.ts';
|
||||
|
||||
const console = new Stickynotes('ditto:trends');
|
||||
|
||||
|
@ -44,10 +44,17 @@ async function updateTrendingNotesCache() {
|
|||
async function updateTrendingHashtagsCache() {
|
||||
console.info('Updating trending hashtags cache...');
|
||||
const kysely = await DittoDB.getInstance();
|
||||
const yesterday = Math.floor((Date.now() - Time.days(1)) / 1000);
|
||||
const signal = AbortSignal.timeout(1000);
|
||||
|
||||
const hashtags = await getTrendingHashtags(kysely, { since: yesterday, limit: 20, threshold: 3 });
|
||||
const yesterday = Math.floor((Date.now() - Time.days(1)) / 1000);
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
|
||||
const hashtags = await getTrendingTagValues(kysely, 't', {
|
||||
since: yesterday,
|
||||
until: now,
|
||||
limit: 20,
|
||||
});
|
||||
|
||||
const signer = new AdminSigner();
|
||||
|
||||
const label = await signer.signEvent({
|
||||
|
@ -56,7 +63,7 @@ async function updateTrendingHashtagsCache() {
|
|||
tags: [
|
||||
['L', 'pub.ditto.trends'],
|
||||
['l', 'hashtags', 'pub.ditto.trends'],
|
||||
...hashtags.map(({ tag }) => ['t', tag]),
|
||||
...hashtags.map(({ value }) => ['t', value]),
|
||||
],
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
});
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
import { Kysely } from 'kysely';
|
||||
|
||||
import { DittoTables } from '@/db/DittoTables.ts';
|
||||
|
||||
interface GetTrendingHashtagsOpts {
|
||||
/** Unix timestamp in _seconds_ for the starting point of this query. */
|
||||
since: number;
|
||||
/** Maximum number of trending hashtags to return. */
|
||||
limit: number;
|
||||
/** Minimum number of unique accounts that have used a hashtag to be considered trending. */
|
||||
threshold: number;
|
||||
}
|
||||
|
||||
/** Get the trending hashtags in the given time frame. */
|
||||
export async function getTrendingHashtags(
|
||||
/** Kysely instance to execute queries on. */
|
||||
kysely: Kysely<DittoTables>,
|
||||
/** Options for this query. */
|
||||
opts: GetTrendingHashtagsOpts,
|
||||
): Promise<{ tag: string; accounts: number; uses: number }[]> {
|
||||
const { since, limit, threshold } = opts;
|
||||
|
||||
return await kysely
|
||||
.selectFrom('nostr_tags')
|
||||
.innerJoin('nostr_events', 'nostr_events.id', 'nostr_tags.event_id')
|
||||
.select(({ fn }) => [
|
||||
'nostr_tags.value as tag',
|
||||
fn.agg<number>('count', ['nostr_events.pubkey']).distinct().as('accounts'),
|
||||
fn.countAll<number>().as('uses'),
|
||||
])
|
||||
.where('nostr_tags.name', '=', 't')
|
||||
.where('nostr_events.created_at', '>', since)
|
||||
.groupBy('nostr_tags.value')
|
||||
.having((c) => c(c.fn.agg('count', ['nostr_events.pubkey']).distinct(), '>=', threshold))
|
||||
.orderBy((c) => c.fn.agg('count', ['nostr_events.pubkey']).distinct(), 'desc')
|
||||
.limit(limit)
|
||||
.execute();
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
import { NostrFilter } from '@nostrify/nostrify';
|
||||
import { Kysely } from 'kysely';
|
||||
|
||||
import { DittoTables } from '@/db/DittoTables.ts';
|
||||
|
||||
/** Get trending tag values for a given tag in the given time frame. */
|
||||
export async function getTrendingTagValues(
|
||||
/** Kysely instance to execute queries on. */
|
||||
kysely: Kysely<DittoTables>,
|
||||
/** Tag name to filter by, eg `t` or `r`. */
|
||||
tagName: string,
|
||||
/** Filter of eligible events. */
|
||||
filter: NostrFilter,
|
||||
): Promise<{ value: string; authors: number; uses: number }[]> {
|
||||
let query = kysely
|
||||
.selectFrom('nostr_tags')
|
||||
.innerJoin('nostr_events', 'nostr_events.id', 'nostr_tags.event_id')
|
||||
.select(({ fn }) => [
|
||||
'nostr_tags.value',
|
||||
fn.agg<number>('count', ['nostr_events.pubkey']).distinct().as('authors'),
|
||||
fn.countAll<number>().as('uses'),
|
||||
])
|
||||
.where('nostr_tags.name', '=', tagName)
|
||||
.groupBy('nostr_tags.value')
|
||||
.orderBy((c) => c.fn.agg('count', ['nostr_events.pubkey']).distinct(), '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) => ({
|
||||
value: row.value,
|
||||
authors: Number(row.authors),
|
||||
uses: Number(row.uses),
|
||||
}));
|
||||
}
|
Loading…
Reference in New Issue