renderStatus: don't fetch the author, expect it to be passed in

This commit is contained in:
Alex Gleason 2023-12-06 12:04:24 -06:00
parent 7d2813b214
commit a6947441fc
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
10 changed files with 40 additions and 29 deletions

View file

@ -1,7 +1,8 @@
import { type AppController } from '@/app.ts'; import { type AppController } from '@/app.ts';
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import { insertUser } from '@/db/users.ts'; import { insertUser } from '@/db/users.ts';
import { type Filter, findReplyTag, nip19, z } from '@/deps.ts'; import { findReplyTag, nip19, z } from '@/deps.ts';
import { type DittoFilter } from '@/filter.ts';
import * as mixer from '@/mixer.ts'; import * as mixer from '@/mixer.ts';
import { getAuthor, getFollowedPubkeys, getFollows } from '@/queries.ts'; import { getAuthor, getFollowedPubkeys, getFollows } from '@/queries.ts';
import { booleanParamSchema, fileSchema } from '@/schema.ts'; import { booleanParamSchema, fileSchema } from '@/schema.ts';
@ -137,7 +138,7 @@ const accountStatusesController: AppController = async (c) => {
return c.json([]); return c.json([]);
} }
const filter: Filter<1> = { authors: [pubkey], kinds: [1], since, until, limit }; const filter: DittoFilter<1> = { authors: [pubkey], kinds: [1], relations: ['author'], since, until, limit };
if (tagged) { if (tagged) {
filter['#t'] = [tagged]; filter['#t'] = [tagged];
} }
@ -256,7 +257,7 @@ const favouritesController: AppController = async (c) => {
.map((event) => event.tags.find((tag) => tag[0] === 'e')?.[1]) .map((event) => event.tags.find((tag) => tag[0] === 'e')?.[1])
.filter((id): id is string => !!id); .filter((id): id is string => !!id);
const events1 = await mixer.getFilters([{ kinds: [1], ids }], { timeout: Time.seconds(1) }); const events1 = await mixer.getFilters([{ kinds: [1], ids, relations: ['author'] }], { timeout: Time.seconds(1) });
const statuses = await Promise.all(events1.map((event) => renderStatus(event, c.get('pubkey')))); const statuses = await Promise.all(events1.map((event) => renderStatus(event, c.get('pubkey'))));
return paginated(c, events1, statuses); return paginated(c, events1, statuses);

View file

@ -1,6 +1,7 @@
import { AppController } from '@/app.ts'; import { AppController } from '@/app.ts';
import * as eventsDB from '@/db/events.ts'; import * as eventsDB from '@/db/events.ts';
import { type Event, type Filter, nip19, z } from '@/deps.ts'; import { type Event, nip19, z } from '@/deps.ts';
import { type DittoFilter } from '@/filter.ts';
import * as mixer from '@/mixer.ts'; import * as mixer from '@/mixer.ts';
import { booleanParamSchema } from '@/schema.ts'; import { booleanParamSchema } from '@/schema.ts';
import { nostrIdSchema } from '@/schemas/nostr.ts'; import { nostrIdSchema } from '@/schemas/nostr.ts';
@ -65,9 +66,10 @@ const searchController: AppController = async (c) => {
function searchEvents({ q, type, limit, account_id }: SearchQuery): Promise<Event[]> { function searchEvents({ q, type, limit, account_id }: SearchQuery): Promise<Event[]> {
if (type === 'hashtags') return Promise.resolve([]); if (type === 'hashtags') return Promise.resolve([]);
const filter: Filter = { const filter: DittoFilter = {
kinds: typeToKinds(type), kinds: typeToKinds(type),
search: q, search: q,
relations: ['author'],
limit, limit,
}; };
@ -98,8 +100,8 @@ async function lookupEvent(query: SearchQuery): Promise<Event | undefined> {
} }
/** Get filters to lookup the input value. */ /** Get filters to lookup the input value. */
async function getLookupFilters({ q, type, resolve }: SearchQuery): Promise<Filter[]> { async function getLookupFilters({ q, type, resolve }: SearchQuery): Promise<DittoFilter[]> {
const filters: Filter[] = []; const filters: DittoFilter[] = [];
const accounts = !type || type === 'accounts'; const accounts = !type || type === 'accounts';
const statuses = !type || type === 'statuses'; const statuses = !type || type === 'statuses';
@ -138,7 +140,7 @@ async function getLookupFilters({ q, type, resolve }: SearchQuery): Promise<Filt
} }
} }
return filters; return filters.map((filter) => ({ ...filter, relations: ['author'] }));
} }
export { searchController }; export { searchController };

View file

@ -1,7 +1,7 @@
import { type AppController } from '@/app.ts'; import { type AppController } from '@/app.ts';
import { getUnattachedMediaByIds } from '@/db/unattached-media.ts'; import { getUnattachedMediaByIds } from '@/db/unattached-media.ts';
import { type Event, ISO6391, z } from '@/deps.ts'; import { type Event, ISO6391, z } from '@/deps.ts';
import { getAncestors, getDescendants, getEvent } from '@/queries.ts'; import { getAncestors, getAuthor, getDescendants, getEvent } from '@/queries.ts';
import { createEvent, paginationSchema, parseBody } from '@/utils/web.ts'; import { createEvent, paginationSchema, parseBody } from '@/utils/web.ts';
import { renderEventAccounts } from '@/views.ts'; import { renderEventAccounts } from '@/views.ts';
import { renderStatus } from '@/views/mastodon/statuses.ts'; import { renderStatus } from '@/views/mastodon/statuses.ts';
@ -29,7 +29,7 @@ const createStatusSchema = z.object({
const statusController: AppController = async (c) => { const statusController: AppController = async (c) => {
const id = c.req.param('id'); const id = c.req.param('id');
const event = await getEvent(id, { kind: 1 }); const event = await getEvent(id, { kind: 1, relations: ['author'] });
if (event) { if (event) {
return c.json(await renderStatus(event, c.get('pubkey'))); return c.json(await renderStatus(event, c.get('pubkey')));
} }
@ -83,12 +83,13 @@ const createStatusController: AppController = async (c) => {
tags, tags,
}, c); }, c);
return c.json(await renderStatus(event, c.get('pubkey'))); const author = await getAuthor(event.pubkey);
return c.json(await renderStatus({ ...event, author }, c.get('pubkey')));
}; };
const contextController: AppController = async (c) => { const contextController: AppController = async (c) => {
const id = c.req.param('id'); const id = c.req.param('id');
const event = await getEvent(id, { kind: 1 }); const event = await getEvent(id, { kind: 1, relations: ['author'] });
async function renderStatuses(events: Event<1>[]) { async function renderStatuses(events: Event<1>[]) {
const statuses = await Promise.all(events.map((event) => renderStatus(event, c.get('pubkey')))); const statuses = await Promise.all(events.map((event) => renderStatus(event, c.get('pubkey'))));
@ -109,7 +110,7 @@ const contextController: AppController = async (c) => {
const favouriteController: AppController = async (c) => { const favouriteController: AppController = async (c) => {
const id = c.req.param('id'); const id = c.req.param('id');
const target = await getEvent(id, { kind: 1 }); const target = await getEvent(id, { kind: 1, relations: ['author'] });
if (target) { if (target) {
await createEvent({ await createEvent({

View file

@ -1,7 +1,7 @@
import { type AppController } from '@/app.ts'; import { type AppController } from '@/app.ts';
import { z } from '@/deps.ts'; import { z } from '@/deps.ts';
import { type DittoFilter } from '@/filter.ts'; import { type DittoFilter } from '@/filter.ts';
import { getFeedPubkeys } from '@/queries.ts'; import { getAuthor, getFeedPubkeys } from '@/queries.ts';
import { Sub } from '@/subs.ts'; import { Sub } from '@/subs.ts';
import { bech32ToPubkey } from '@/utils.ts'; import { bech32ToPubkey } from '@/utils.ts';
import { renderStatus } from '@/views/mastodon/statuses.ts'; import { renderStatus } from '@/views/mastodon/statuses.ts';
@ -63,7 +63,8 @@ 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])) {
const status = await renderStatus(event, pubkey); const author = await getAuthor(event.pubkey);
const status = await renderStatus({ ...event, author }, pubkey);
if (status) { if (status) {
send('update', status); send('update', status);
} }

View file

@ -34,7 +34,10 @@ const hashtagTimelineController: AppController = (c) => {
/** Render statuses for timelines. */ /** Render statuses for timelines. */
async function renderStatuses(c: AppContext, filters: DittoFilter<1>[]) { async function renderStatuses(c: AppContext, filters: DittoFilter<1>[]) {
const events = await mixer.getFilters(filters, { timeout: Time.seconds(1) }); const events = await mixer.getFilters(
filters.map((filter) => ({ ...filter, relations: ['author'] })),
{ timeout: Time.seconds(1) },
);
if (!events.length) { if (!events.length) {
return c.json([]); return c.json([]);

View file

@ -304,4 +304,4 @@ function buildUserSearchContent(event: Event<0>): string {
return [name, nip05, about].filter(Boolean).join('\n'); return [name, nip05, about].filter(Boolean).join('\n');
} }
export { countFilters, deleteFilters, getFilters, insertEvent }; export { countFilters, deleteFilters, type DittoEvent, getFilters, insertEvent };

View file

@ -44,4 +44,4 @@ function matchDittoFilters(filters: DittoFilter[], event: Event, data: EventData
return false; return false;
} }
export { type DittoFilter, type GetFiltersOpts, matchDittoFilters }; export { type DittoFilter, type GetFiltersOpts, matchDittoFilters, type Relation };

View file

@ -1,5 +1,6 @@
import * as eventsDB from '@/db/events.ts'; import * as eventsDB from '@/db/events.ts';
import { type Event, type Filter, findReplyTag } from '@/deps.ts'; import { type Event, findReplyTag } from '@/deps.ts';
import { type DittoFilter, type Relation } from '@/filter.ts';
import * as mixer from '@/mixer.ts'; import * as mixer from '@/mixer.ts';
interface GetEventOpts<K extends number> { interface GetEventOpts<K extends number> {
@ -7,6 +8,8 @@ interface GetEventOpts<K extends number> {
timeout?: number; timeout?: number;
/** Event kind. */ /** Event kind. */
kind?: K; kind?: K;
/** Relations to include on the event. */
relations?: Relation[];
} }
/** Get a Nostr event by its ID. */ /** Get a Nostr event by its ID. */
@ -14,8 +17,8 @@ const getEvent = async <K extends number = number>(
id: string, id: string,
opts: GetEventOpts<K> = {}, opts: GetEventOpts<K> = {},
): Promise<Event<K> | undefined> => { ): Promise<Event<K> | undefined> => {
const { kind, timeout = 1000 } = opts; const { kind, relations, timeout = 1000 } = opts;
const filter: Filter<K> = { ids: [id], limit: 1 }; const filter: DittoFilter<K> = { ids: [id], relations, limit: 1 };
if (kind) { if (kind) {
filter.kinds = [kind]; filter.kinds = [kind];
} }
@ -57,7 +60,7 @@ async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise
const inReplyTo = replyTag ? replyTag[1] : undefined; const inReplyTo = replyTag ? replyTag[1] : undefined;
if (inReplyTo) { if (inReplyTo) {
const parentEvent = await getEvent(inReplyTo, { kind: 1 }); const parentEvent = await getEvent(inReplyTo, { kind: 1, relations: ['author'] });
if (parentEvent) { if (parentEvent) {
result.push(parentEvent); result.push(parentEvent);
@ -70,7 +73,7 @@ async function getAncestors(event: Event<1>, result = [] as Event<1>[]): Promise
} }
function getDescendants(eventId: string): Promise<Event<1>[]> { function getDescendants(eventId: string): Promise<Event<1>[]> {
return mixer.getFilters([{ kinds: [1], '#e': [eventId] }], { limit: 200, timeout: 2000 }); return mixer.getFilters([{ kinds: [1], '#e': [eventId], relations: ['author'] }], { limit: 200, timeout: 2000 });
} }
/** Returns whether the pubkey is followed by a local user. */ /** Returns whether the pubkey is followed by a local user. */

View file

@ -1,4 +1,5 @@
import { type Event } from '@/deps.ts'; import { type Event } from '@/deps.ts';
import { getAuthor } from '@/queries.ts';
import { nostrDate } from '@/utils.ts'; import { nostrDate } from '@/utils.ts';
import { accountFromPubkey } from '@/views/mastodon/accounts.ts'; import { accountFromPubkey } from '@/views/mastodon/accounts.ts';
import { renderStatus } from '@/views/mastodon/statuses.ts'; import { renderStatus } from '@/views/mastodon/statuses.ts';
@ -11,7 +12,8 @@ function renderNotification(event: Event, viewerPubkey?: string) {
} }
async function renderNotificationMention(event: Event<1>, viewerPubkey?: string) { async function renderNotificationMention(event: Event<1>, viewerPubkey?: string) {
const status = await renderStatus(event, viewerPubkey); const author = await getAuthor(event.pubkey);
const status = await renderStatus({ ...event, author }, viewerPubkey);
if (!status) return; if (!status) return;
return { return {

View file

@ -2,7 +2,7 @@ import { isCWTag } from 'https://gitlab.com/soapbox-pub/mostr/-/raw/c67064aee5ad
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import * as eventsDB from '@/db/events.ts'; import * as eventsDB from '@/db/events.ts';
import { type Event, findReplyTag, nip19 } from '@/deps.ts'; import { findReplyTag, nip19 } from '@/deps.ts';
import { getMediaLinks, parseNoteContent } from '@/note.ts'; import { getMediaLinks, parseNoteContent } from '@/note.ts';
import { getAuthor } from '@/queries.ts'; import { getAuthor } from '@/queries.ts';
import { jsonMediaDataSchema } from '@/schemas/nostr.ts'; import { jsonMediaDataSchema } from '@/schemas/nostr.ts';
@ -12,10 +12,8 @@ import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts';
import { DittoAttachment, renderAttachment } from '@/views/mastodon/attachments.ts'; import { DittoAttachment, renderAttachment } from '@/views/mastodon/attachments.ts';
import { renderEmojis } from '@/views/mastodon/emojis.ts'; import { renderEmojis } from '@/views/mastodon/emojis.ts';
async function renderStatus(event: Event<1>, viewerPubkey?: string) { async function renderStatus(event: eventsDB.DittoEvent<1>, viewerPubkey?: string) {
const profile = await getAuthor(event.pubkey); const account = event.author ? await renderAccount(event.author) : await accountFromPubkey(event.pubkey);
const account = profile ? await renderAccount(profile) : await accountFromPubkey(event.pubkey);
const replyTag = findReplyTag(event); const replyTag = findReplyTag(event);
const mentionedPubkeys = [ const mentionedPubkeys = [