diff --git a/src/pipeline.ts b/src/pipeline.ts index f1875701..1c7a891d 100644 --- a/src/pipeline.ts +++ b/src/pipeline.ts @@ -7,9 +7,8 @@ import { Debug, LNURL, type NostrEvent } from '@/deps.ts'; import { DittoEvent } from '@/interfaces/DittoEvent.ts'; import { isEphemeralKind } from '@/kinds.ts'; import { DVM } from '@/pipeline/DVM.ts'; -import { getAuthor } from '@/queries.ts'; import { updateStats } from '@/stats.ts'; -import { purifyEvent } from '@/storages/hydrate.ts'; +import { hydrateEvents, purifyEvent } from '@/storages/hydrate.ts'; import { cache, client, eventsDB, reqmeister } from '@/storages.ts'; import { Sub } from '@/subs.ts'; import { getTagSet } from '@/tags.ts'; @@ -31,7 +30,7 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise ${event.id}`); - await hydrateEvent(event); + await hydrateEvent(event, signal); await Promise.all([ storeEvent(event, signal), @@ -57,12 +56,8 @@ async function encounterEvent(event: NostrEvent, signal: AbortSignal): Promise { - const [user] = await eventsDB.query([{ kinds: [30361], authors: [Conf.pubkey], '#d': [event.pubkey], limit: 1 }]); - event.user = user; - - const author = await getAuthor(event.pubkey); - event.author = author; +async function hydrateEvent(event: DittoEvent, signal: AbortSignal): Promise { + await hydrateEvents({ events: [event], relations: ['author', 'user'], storage: eventsDB, signal }); const domain = await db .selectFrom('pubkey_domains') diff --git a/src/storages/hydrate.ts b/src/storages/hydrate.ts index 6a92d807..e56ebe6f 100644 --- a/src/storages/hydrate.ts +++ b/src/storages/hydrate.ts @@ -1,3 +1,4 @@ +import { Conf } from '@/config.ts'; import { db } from '@/db.ts'; import { type NostrEvent, type NStore } from '@/deps.ts'; import { type DittoEvent } from '@/interfaces/DittoEvent.ts'; @@ -29,6 +30,9 @@ async function hydrateEvents(opts: HydrateEventOpts): Promise { case 'event_stats': await hydrateEventStats(events); break; + case 'user': + await hydrateUsers({ events, storage, signal }); + break; } } @@ -48,6 +52,23 @@ async function hydrateAuthors(opts: Omit): Promis return events; } +async function hydrateUsers(opts: Omit): Promise { + const { events, storage, signal } = opts; + + const pubkeys = new Set([...events].map((event) => event.pubkey)); + + const users = await storage.query( + [{ kinds: [30361], authors: [Conf.pubkey], '#d': [...pubkeys], limit: pubkeys.size }], + { signal }, + ); + + for (const event of events) { + event.user = users.find((user) => user.tags.find(([name]) => name === 'd')?.[1] === event.pubkey); + } + + return events; +} + async function hydrateAuthorStats(events: DittoEvent[]): Promise { const results = await db .selectFrom('author_stats') diff --git a/src/views/mastodon/accounts.ts b/src/views/mastodon/accounts.ts index 3fc8181b..7f25e5ee 100644 --- a/src/views/mastodon/accounts.ts +++ b/src/views/mastodon/accounts.ts @@ -1,5 +1,4 @@ import { Conf } from '@/config.ts'; -import { findUser } from '@/db/users.ts'; import { lodash, nip19, type UnsignedEvent } from '@/deps.ts'; import { type DittoEvent } from '@/interfaces/DittoEvent.ts'; import { jsonMetaContentSchema } from '@/schemas/nostr.ts'; @@ -30,11 +29,8 @@ async function renderAccount( } = jsonMetaContentSchema.parse(event.content); const npub = nip19.npubEncode(pubkey); - - const [user, parsed05] = await Promise.all([ - findUser({ pubkey }), - parseAndVerifyNip05(nip05, pubkey), - ]); + const parsed05 = await parseAndVerifyNip05(nip05, pubkey); + const role = event.user?.tags.find(([name]) => name === 'role')?.[1] ?? 'user'; return { id: pubkey, @@ -42,7 +38,7 @@ async function renderAccount( avatar: picture, avatar_static: picture, bot: false, - created_at: user ? user.inserted_at.toISOString() : nostrDate(event.created_at).toISOString(), + created_at: nostrDate(event.user?.created_at ?? event.created_at).toISOString(), discoverable: true, display_name: name, emojis: renderEmojis(event), @@ -75,11 +71,11 @@ async function renderAccount( username: parsed05?.nickname || npub.substring(0, 8), ditto: { accepts_zaps: Boolean(getLnurl({ lud06, lud16 })), - is_registered: Boolean(user), + is_registered: Boolean(event.user), }, pleroma: { - is_admin: user?.admin || false, - is_moderator: user?.admin || false, + is_admin: role === 'admin', + is_moderator: ['admin', 'moderator'].includes(role), }, nostr: { pubkey,