Merge branch 'hydrate-stats' into 'main'

hydrateEvents: restore stats

See merge request soapbox-pub/ditto!123
This commit is contained in:
Alex Gleason 2024-03-30 22:46:33 +00:00
commit ed5e04f558
2 changed files with 52 additions and 1 deletions

View File

@ -48,7 +48,9 @@ async function renderStatuses(c: AppContext, filters: NostrFilter[]) {
const events = await eventsDB const events = await eventsDB
.query(filters, { signal }) .query(filters, { signal })
.then((events) => hydrateEvents({ events, relations: ['author'], storage: eventsDB, signal })); .then((events) =>
hydrateEvents({ events, relations: ['author', 'author_stats', 'event_stats'], storage: eventsDB, signal })
);
if (!events.length) { if (!events.length) {
return c.json([]); return c.json([]);

View File

@ -1,3 +1,4 @@
import { db } from '@/db.ts';
import { type NostrEvent, type NStore } from '@/deps.ts'; import { type NostrEvent, type NStore } from '@/deps.ts';
import { type DittoEvent } from '@/interfaces/DittoEvent.ts'; import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
import { type DittoRelation } from '@/interfaces/DittoFilter.ts'; import { type DittoRelation } from '@/interfaces/DittoFilter.ts';
@ -22,6 +23,12 @@ async function hydrateEvents(opts: HydrateEventOpts): Promise<DittoEvent[]> {
case 'author': case 'author':
await hydrateAuthors({ events, storage, signal }); await hydrateAuthors({ events, storage, signal });
break; break;
case 'author_stats':
await hydrateAuthorStats(events);
break;
case 'event_stats':
await hydrateEventStats(events);
break;
} }
} }
@ -41,6 +48,48 @@ async function hydrateAuthors(opts: Omit<HydrateEventOpts, 'relations'>): Promis
return events; return events;
} }
async function hydrateAuthorStats(events: DittoEvent[]): Promise<DittoEvent[]> {
const results = await db
.selectFrom('author_stats')
.selectAll()
.where('pubkey', 'in', events.map((event) => event.pubkey))
.execute();
for (const event of events) {
const stat = results.find((result) => result.pubkey === event.pubkey);
if (stat) {
event.author_stats = {
followers_count: Math.max(stat.followers_count, 0) || 0,
following_count: Math.max(stat.following_count, 0) || 0,
notes_count: Math.max(stat.notes_count, 0) || 0,
};
}
}
return events;
}
async function hydrateEventStats(events: DittoEvent[]): Promise<DittoEvent[]> {
const results = await db
.selectFrom('event_stats')
.selectAll()
.where('event_id', 'in', events.map((event) => event.id))
.execute();
for (const event of events) {
const stat = results.find((result) => result.event_id === event.id);
if (stat) {
event.event_stats = {
replies_count: Math.max(stat.replies_count, 0) || 0,
reposts_count: Math.max(stat.reposts_count, 0) || 0,
reactions_count: Math.max(stat.reactions_count, 0) || 0,
};
}
}
return events;
}
/** Return a normalized event without any non-standard keys. */ /** Return a normalized event without any non-standard keys. */
function purifyEvent(event: NostrEvent): NostrEvent { function purifyEvent(event: NostrEvent): NostrEvent {
return { return {