perf: hydrate repost event in home timeline
This commit is contained in:
parent
581ecd67d6
commit
24efca5ea0
|
@ -226,7 +226,7 @@ const reblogStatusController: AppController = async (c) => {
|
||||||
tags: [['e', event.id], ['p', event.pubkey]],
|
tags: [['e', event.id], ['p', event.pubkey]],
|
||||||
}, c);
|
}, c);
|
||||||
|
|
||||||
const status = await renderReblog(reblogEvent);
|
const status = await renderReblog(reblogEvent, { loadOriginalPostEvent: true });
|
||||||
|
|
||||||
return c.json(status);
|
return c.json(status);
|
||||||
};
|
};
|
||||||
|
|
|
@ -64,7 +64,7 @@ const streamingController: AppController = (c) => {
|
||||||
if (filter) {
|
if (filter) {
|
||||||
for await (const event of Sub.sub(socket, '1', [filter])) {
|
for await (const event of Sub.sub(socket, '1', [filter])) {
|
||||||
if (event.kind === 6) {
|
if (event.kind === 6) {
|
||||||
const status = await renderReblog(event);
|
const status = await renderReblog(event, { loadOriginalPostEvent: true });
|
||||||
if (status) {
|
if (status) {
|
||||||
send('update', status);
|
send('update', status);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,12 @@ async function renderStatuses(c: AppContext, filters: NostrFilter[]) {
|
||||||
const events = await eventsDB
|
const events = await eventsDB
|
||||||
.query(filters, { signal })
|
.query(filters, { signal })
|
||||||
.then((events) =>
|
.then((events) =>
|
||||||
hydrateEvents({ events, relations: ['author', 'author_stats', 'event_stats'], storage: eventsDB, signal })
|
hydrateEvents({
|
||||||
|
events,
|
||||||
|
relations: ['author', 'author_stats', 'event_stats', 'repost'],
|
||||||
|
storage: eventsDB,
|
||||||
|
signal,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!events.length) {
|
if (!events.length) {
|
||||||
|
@ -58,7 +63,7 @@ async function renderStatuses(c: AppContext, filters: NostrFilter[]) {
|
||||||
|
|
||||||
const statuses = (await Promise.all(events.map((event) => {
|
const statuses = (await Promise.all(events.map((event) => {
|
||||||
if (event.kind === 6) {
|
if (event.kind === 6) {
|
||||||
return renderReblog(event);
|
return renderReblog(event, {});
|
||||||
}
|
}
|
||||||
return renderStatus(event, c.get('pubkey'));
|
return renderStatus(event, c.get('pubkey'));
|
||||||
}))).filter((boolean) => boolean);
|
}))).filter((boolean) => boolean);
|
||||||
|
|
|
@ -3,6 +3,7 @@ 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';
|
||||||
|
import { eventsDB } from '@/storages.ts';
|
||||||
|
|
||||||
interface HydrateEventOpts {
|
interface HydrateEventOpts {
|
||||||
events: DittoEvent[];
|
events: DittoEvent[];
|
||||||
|
@ -33,6 +34,9 @@ async function hydrateEvents(opts: HydrateEventOpts): Promise<DittoEvent[]> {
|
||||||
case 'user':
|
case 'user':
|
||||||
await hydrateUsers({ events, storage, signal });
|
await hydrateUsers({ events, storage, signal });
|
||||||
break;
|
break;
|
||||||
|
case 'repost':
|
||||||
|
await hydrateRepostEvents(events);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +115,24 @@ async function hydrateEventStats(events: DittoEvent[]): Promise<DittoEvent[]> {
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function hydrateRepostEvents(events: DittoEvent[]): Promise<DittoEvent[]> {
|
||||||
|
const results = await eventsDB.query([{ kinds: [1], ids: events.map((event) => event.id) }]);
|
||||||
|
|
||||||
|
for (const event of events) {
|
||||||
|
if (event.kind === 6) {
|
||||||
|
const originalPostId = event.tags.find(([name]) => name === 'e')?.[1];
|
||||||
|
if (!originalPostId) continue;
|
||||||
|
|
||||||
|
const originalPostEvent = results.find((event) => event.id === originalPostId);
|
||||||
|
if (!originalPostEvent) continue;
|
||||||
|
|
||||||
|
event.repost = originalPostEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
|
@ -100,13 +100,21 @@ async function renderStatus(event: DittoEvent, viewerPubkey?: string) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function renderReblog(event: DittoEvent) {
|
type reblogOpts = {
|
||||||
|
loadOriginalPostEvent?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function renderReblog(event: DittoEvent, opts: reblogOpts) {
|
||||||
|
const { loadOriginalPostEvent } = opts;
|
||||||
|
|
||||||
if (!event.author) return;
|
if (!event.author) return;
|
||||||
|
|
||||||
const repostId = event.tags.find(([name]) => name === 'e')?.[1];
|
const repostId = event.tags.find(([name]) => name === 'e')?.[1];
|
||||||
if (!repostId) return;
|
if (!repostId) return;
|
||||||
|
|
||||||
event.repost = await getEvent(repostId, { kind: 1 });
|
if (loadOriginalPostEvent) {
|
||||||
|
event.repost = await getEvent(repostId, { kind: 1 });
|
||||||
|
}
|
||||||
if (!event.repost) return;
|
if (!event.repost) return;
|
||||||
|
|
||||||
const reblog = await renderStatus(event.repost);
|
const reblog = await renderStatus(event.repost);
|
||||||
|
|
Loading…
Reference in New Issue