mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
Render client tags
This commit is contained in:
parent
caf59f4078
commit
23eb531305
4 changed files with 59 additions and 4 deletions
|
|
@ -56,4 +56,5 @@ export interface DittoEvent extends NostrEvent {
|
|||
zap_message?: string;
|
||||
/** Language of the event (kind 1s are more accurate). */
|
||||
language?: LanguageCode;
|
||||
client?: DittoEvent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { DittoDB, DittoTables } from '@ditto/db';
|
||||
import { DittoConf } from '@ditto/conf';
|
||||
import { NStore } from '@nostrify/nostrify';
|
||||
import { type NostrFilter, NStore } from '@nostrify/nostrify';
|
||||
import { Kysely } from 'kysely';
|
||||
import { matchFilter } from 'nostr-tools';
|
||||
import { NSchema as n } from '@nostrify/nostrify';
|
||||
|
|
@ -50,6 +50,10 @@ async function hydrateEvents(opts: HydrateOpts): Promise<DittoEvent[]> {
|
|||
cache.push(event);
|
||||
}
|
||||
|
||||
for (const event of await gatherClients({ ...opts, events: cache })) {
|
||||
cache.push(event);
|
||||
}
|
||||
|
||||
const authorStats = await gatherAuthorStats(cache, db.kysely);
|
||||
const eventStats = await gatherEventStats(cache, db.kysely);
|
||||
|
||||
|
|
@ -128,6 +132,16 @@ export function assembleEvents(
|
|||
event.user = b.find((e) => matchFilter({ kinds: [30382], authors: [admin], '#d': [event.pubkey] }, e));
|
||||
event.info = b.find((e) => matchFilter({ kinds: [30383], authors: [admin], '#d': [event.id] }, e));
|
||||
|
||||
for (const [name, _value, addr] of event.tags) {
|
||||
if (name === 'client' && addr) {
|
||||
const match = addr.match(/^31990:([0-9a-f]{64}):(.+)$/);
|
||||
if (match) {
|
||||
const [, pubkey, d] = match;
|
||||
event.client = b.find((e) => matchFilter({ kinds: [31990], authors: [pubkey], '#d': [d] }, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.kind === 1) {
|
||||
const id = findQuoteTag(event.tags)?.[1] || findQuoteInContent(event.content);
|
||||
if (id) {
|
||||
|
|
@ -353,6 +367,28 @@ async function gatherInfo({ conf, events, relay, signal }: HydrateOpts): Promise
|
|||
);
|
||||
}
|
||||
|
||||
function gatherClients({ events, relay, signal }: HydrateOpts): Promise<DittoEvent[]> {
|
||||
const filters: NostrFilter[] = [];
|
||||
|
||||
for (const event of events) {
|
||||
for (const [name, _value, addr] of event.tags) {
|
||||
if (name === 'client' && addr) {
|
||||
const match = addr.match(/^31990:([0-9a-f]{64}):(.+)$/);
|
||||
if (match) {
|
||||
const [, pubkey, d] = match;
|
||||
filters.push({ kinds: [31990], authors: [pubkey], '#d': [d], limit: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!filters.length) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
return relay.query(filters, { signal });
|
||||
}
|
||||
|
||||
/** Collect author stats from the events. */
|
||||
async function gatherAuthorStats(
|
||||
events: DittoEvent[],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { NostrEvent, NStore } from '@nostrify/nostrify';
|
||||
import { NostrEvent, NSchema as n, NStore } from '@nostrify/nostrify';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
|
||||
import { Conf } from '@/config.ts';
|
||||
|
|
@ -118,11 +118,27 @@ async function renderStatus(
|
|||
return acc;
|
||||
}, [] as { name: string; count: number; me: boolean; url?: string }[]);
|
||||
|
||||
let application: MastodonStatus['application'] = undefined;
|
||||
|
||||
if (event.client) {
|
||||
const result = n.json().pipe(n.metadata()).safeParse(event.client.content);
|
||||
if (result.success) {
|
||||
const name = result.data.name ?? result.data.display_name ?? event.tags.find(([name]) => name === 'client')?.[1];
|
||||
if (name) {
|
||||
application = {
|
||||
name,
|
||||
website: result.data.website ?? null,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expiresAt = new Date(Number(event.tags.find(([name]) => name === 'expiration')?.[1]) * 1000);
|
||||
|
||||
return {
|
||||
id: event.id,
|
||||
account,
|
||||
application,
|
||||
card: event.event_stats?.link_preview ?? null,
|
||||
content: compatMentions + html,
|
||||
created_at: nostrDate(event.created_at).toISOString(),
|
||||
|
|
@ -142,7 +158,6 @@ async function renderStatus(
|
|||
bookmarked: Boolean(bookmarkEvent),
|
||||
pinned: Boolean(pinEvent),
|
||||
reblog: null,
|
||||
application: null,
|
||||
media_attachments: media
|
||||
.map((m) => renderAttachment({ tags: m }))
|
||||
.filter((m): m is MastodonAttachment => Boolean(m)),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ import type { MastodonPreviewCard } from './MastodonPreviewCard.ts';
|
|||
export interface MastodonStatus {
|
||||
id: string;
|
||||
account: MastodonAccount;
|
||||
application?: {
|
||||
name: string;
|
||||
website: string | null;
|
||||
};
|
||||
card: MastodonPreviewCard | null;
|
||||
content: string;
|
||||
created_at: string;
|
||||
|
|
@ -24,7 +28,6 @@ export interface MastodonStatus {
|
|||
bookmarked: boolean;
|
||||
pinned: boolean;
|
||||
reblog: MastodonStatus | null;
|
||||
application: unknown;
|
||||
media_attachments: MastodonAttachment[];
|
||||
mentions: unknown[];
|
||||
tags: unknown[];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue