Merge branch 'quote-content' into 'main'

Find quote ID in content

See merge request soapbox-pub/ditto!357
This commit is contained in:
Alex Gleason 2024-06-04 22:49:51 +00:00
commit ea73ac2da2
3 changed files with 25 additions and 9 deletions

View File

@ -6,6 +6,7 @@ import { DittoTables } from '@/db/DittoTables.ts';
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import { type DittoEvent } from '@/interfaces/DittoEvent.ts'; import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
import { findQuoteTag } from '@/utils/tags.ts'; import { findQuoteTag } from '@/utils/tags.ts';
import { findQuoteInContent } from '@/utils/note.ts';
interface HydrateOpts { interface HydrateOpts {
events: DittoEvent[]; events: DittoEvent[];
@ -84,7 +85,7 @@ export function assembleEvents(
event.user = b.find((e) => matchFilter({ kinds: [30361], authors: [admin], '#d': [event.pubkey] }, e)); event.user = b.find((e) => matchFilter({ kinds: [30361], authors: [admin], '#d': [event.pubkey] }, e));
if (event.kind === 1) { if (event.kind === 1) {
const id = findQuoteTag(event.tags)?.[1]; const id = findQuoteTag(event.tags)?.[1] || findQuoteInContent(event.content);
if (id) { if (id) {
event.quote = b.find((e) => matchFilter({ kinds: [1], ids: [id] }, e)); event.quote = b.find((e) => matchFilter({ kinds: [1], ids: [id] }, e));
} }
@ -172,7 +173,7 @@ function gatherQuotes({ events, store, signal }: HydrateOpts): Promise<DittoEven
for (const event of events) { for (const event of events) {
if (event.kind === 1) { if (event.kind === 1) {
const id = findQuoteTag(event.tags)?.[1]; const id = findQuoteTag(event.tags)?.[1] || findQuoteInContent(event.content);
if (id) { if (id) {
ids.add(id); ids.add(id);
} }

View File

@ -1,7 +1,7 @@
import 'linkify-plugin-hashtag'; import 'linkify-plugin-hashtag';
import linkifyStr from 'linkify-string'; import linkifyStr from 'linkify-string';
import linkify from 'linkifyjs'; import linkify from 'linkifyjs';
import { nip19, nip21 } from 'nostr-tools'; import { nip19, nip21, nip27 } from 'nostr-tools';
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import { getUrlMediaType, isPermittedMediaType } from '@/utils/media.ts'; import { getUrlMediaType, isPermittedMediaType } from '@/utils/media.ts';
@ -118,4 +118,20 @@ function getDecodedPubkey(decoded: nip19.DecodeResult): string | undefined {
} }
} }
export { getMediaLinks, parseNoteContent, stripimeta }; /** Find a quote in the content. */
function findQuoteInContent(content: string): string | undefined {
try {
for (const { decoded } of nip27.matchAll(content)) {
switch (decoded.type) {
case 'note':
return decoded.data;
case 'nevent':
return decoded.data.id;
}
}
} catch (_) {
// do nothing
}
}
export { findQuoteInContent, getMediaLinks, parseNoteContent, stripimeta };

View File

@ -6,7 +6,7 @@ import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
import { Storages } from '@/storages.ts'; import { Storages } from '@/storages.ts';
import { nostrDate } from '@/utils.ts'; import { nostrDate } from '@/utils.ts';
import { getMediaLinks, parseNoteContent, stripimeta } from '@/utils/note.ts'; import { getMediaLinks, parseNoteContent, stripimeta } from '@/utils/note.ts';
import { findQuoteTag, findReplyTag } from '@/utils/tags.ts'; import { findReplyTag } from '@/utils/tags.ts';
import { unfurlCardCached } from '@/utils/unfurl.ts'; import { unfurlCardCached } from '@/utils/unfurl.ts';
import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts'; import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts';
import { renderAttachment } from '@/views/mastodon/attachments.ts'; import { renderAttachment } from '@/views/mastodon/attachments.ts';
@ -28,8 +28,7 @@ async function renderStatus(event: DittoEvent, opts: RenderStatusOpts): Promise<
? await renderAccount({ ...event.author, author_stats: event.author_stats }) ? await renderAccount({ ...event.author, author_stats: event.author_stats })
: await accountFromPubkey(event.pubkey); : await accountFromPubkey(event.pubkey);
const replyTag = findReplyTag(event.tags); const replyId = findReplyTag(event.tags)?.[1];
const quoteTag = findQuoteTag(event.tags);
const mentionedPubkeys = [ const mentionedPubkeys = [
...new Set( ...new Set(
@ -96,7 +95,7 @@ async function renderStatus(event: DittoEvent, opts: RenderStatusOpts): Promise<
card, card,
content, content,
created_at: nostrDate(event.created_at).toISOString(), created_at: nostrDate(event.created_at).toISOString(),
in_reply_to_id: replyTag?.[1] ?? null, in_reply_to_id: replyId ?? null,
in_reply_to_account_id: null, in_reply_to_account_id: null,
sensitive: !!cw, sensitive: !!cw,
spoiler_text: (cw ? cw[1] : subject?.[1]) || '', spoiler_text: (cw ? cw[1] : subject?.[1]) || '',
@ -118,7 +117,7 @@ async function renderStatus(event: DittoEvent, opts: RenderStatusOpts): Promise<
emojis: renderEmojis(event), emojis: renderEmojis(event),
poll: null, poll: null,
quote: !event.quote ? null : await renderStatus(event.quote, { depth: depth + 1 }), quote: !event.quote ? null : await renderStatus(event.quote, { depth: depth + 1 }),
quote_id: quoteTag?.[1] ?? null, quote_id: event.quote?.id ?? null,
uri: Conf.external(note), uri: Conf.external(note),
url: Conf.external(note), url: Conf.external(note),
zapped: Boolean(zapEvent), zapped: Boolean(zapEvent),