Fix mentions in statuses?

This commit is contained in:
Alex Gleason 2025-02-07 19:05:37 -06:00
parent 7780507a15
commit 5811a19151
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
3 changed files with 44 additions and 21 deletions

View file

@ -30,6 +30,7 @@ export interface DittoEvent extends NostrEvent {
author_domain?: string;
author_stats?: AuthorStats;
event_stats?: EventStats;
mentions?: DittoEvent[];
user?: DittoEvent;
repost?: DittoEvent;
quote?: DittoEvent;

View file

@ -30,6 +30,10 @@ async function hydrateEvents(opts: HydrateOpts): Promise<DittoEvent[]> {
const cache = [...events];
for (const event of await gatherMentions({ events: cache, store, signal })) {
cache.push(event);
}
for (const event of await gatherReposts({ events: cache, store, signal })) {
cache.push(event);
}
@ -146,6 +150,9 @@ export function assembleEvents(
if (id) {
event.quote = b.find((e) => matchFilter({ kinds: [1, 20], ids: [id] }, e));
}
const pubkeys = event.tags.filter(([name]) => name === 'p').map(([_name, value]) => value);
event.mentions = b.filter((e) => matchFilter({ kinds: [0], authors: pubkeys }, e));
}
if (event.kind === 6) {
@ -267,6 +274,35 @@ function gatherQuotes({ events, store, signal }: HydrateOpts): Promise<DittoEven
);
}
/** Collect mentioned profiles from notes. */
async function gatherMentions({ events, store, signal }: HydrateOpts): Promise<DittoEvent[]> {
const pubkeys = new Set<string>();
for (const event of events) {
if (event.kind === 1) {
const pubkey = event.tags.find(([name]) => name === 'p')?.[1];
if (pubkey) {
pubkeys.add(pubkey);
}
}
}
const authors = await store.query(
[{ kinds: [0], authors: [...pubkeys], limit: pubkeys.size }],
{ signal },
);
for (const pubkey of pubkeys) {
const author = authors.find((e) => matchFilter({ kinds: [0], authors: [pubkey] }, e));
if (!author) {
const fallback = fallbackAuthor(pubkey);
authors.push(fallback);
}
}
return authors;
}
/** Collect authors from the events. */
async function gatherAuthors({ events, store, signal }: HydrateOpts): Promise<DittoEvent[]> {
const pubkeys = new Set<string>();
@ -297,7 +333,7 @@ async function gatherAuthors({ events, store, signal }: HydrateOpts): Promise<Di
for (const pubkey of pubkeys) {
const author = authors.find((e) => matchFilter({ kinds: [0], authors: [pubkey] }, e));
if (author) {
if (!author) {
const fallback = fallbackAuthor(pubkey);
authors.push(fallback);
}

View file

@ -7,7 +7,7 @@ import { MastodonMention } from '@/entities/MastodonMention.ts';
import { MastodonStatus } from '@/entities/MastodonStatus.ts';
import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
import { Storages } from '@/storages.ts';
import { isNostrId, nostrDate } from '@/utils.ts';
import { nostrDate } from '@/utils.ts';
import { getMediaLinks, parseNoteContent, stripimeta } from '@/utils/note.ts';
import { findReplyTag } from '@/utils/tags.ts';
import { unfurlCardCached } from '@/utils/unfurl.ts';
@ -33,28 +33,14 @@ async function renderStatus(event: DittoEvent, opts: RenderStatusOpts): Promise<
});
const account = event.author
? await renderAccount({ ...event.author, author_stats: event.author_stats })
: await accountFromPubkey(event.pubkey);
? renderAccount({ ...event.author, author_stats: event.author_stats })
: accountFromPubkey(event.pubkey);
const replyId = findReplyTag(event.tags)?.[1];
const mentionedPubkeys = [
...new Set(
event.tags
.filter(([name, value]) => name === 'p' && isNostrId(value))
.map(([, value]) => value),
),
];
const store = await Storages.db();
const mentionedProfiles = await store.query(
[{ kinds: [0], authors: mentionedPubkeys, limit: mentionedPubkeys.length }],
);
const mentions = await Promise.all(
mentionedPubkeys.map((pubkey) => renderMention(pubkey, mentionedProfiles.find((event) => event.pubkey === pubkey))),
);
const mentions = event.mentions?.map((event) => renderMention(event)) ?? [];
const { html, links, firstUrl } = parseNoteContent(stripimeta(event.content, event.tags), mentions);
@ -170,8 +156,8 @@ async function renderReblog(event: DittoEvent, opts: RenderStatusOpts): Promise<
};
}
async function renderMention(pubkey: string, event?: NostrEvent): Promise<MastodonMention> {
const account = event ? await renderAccount(event) : await accountFromPubkey(pubkey);
function renderMention(event: NostrEvent): MastodonMention {
const account = renderAccount(event);
return {
id: account.id,
acct: account.acct,