mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
Support kind 20 "Picture" events (NIP-68)
This commit is contained in:
parent
5a32964eb5
commit
7a60b4b8d8
13 changed files with 31 additions and 31 deletions
|
|
@ -47,7 +47,7 @@ const importUsers = async (
|
||||||
if (!profilesOnly) {
|
if (!profilesOnly) {
|
||||||
matched.push(
|
matched.push(
|
||||||
...await conn.query(
|
...await conn.query(
|
||||||
authors.map((author) => ({ kinds: [1], authors: [author], limit: 200 })),
|
authors.map((author) => ({ kinds: [1, 20], authors: [author], limit: 200 })),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ class Conf {
|
||||||
}
|
}
|
||||||
/** Nostr event kinds of events to listen for on the firehose. */
|
/** Nostr event kinds of events to listen for on the firehose. */
|
||||||
static get firehoseKinds(): number[] {
|
static get firehoseKinds(): number[] {
|
||||||
return (Deno.env.get('FIREHOSE_KINDS') ?? '0, 1, 3, 5, 6, 7, 9735, 10002')
|
return (Deno.env.get('FIREHOSE_KINDS') ?? '0, 1, 3, 5, 6, 7, 20, 9735, 10002')
|
||||||
.split(/[, ]+/g)
|
.split(/[, ]+/g)
|
||||||
.map(Number);
|
.map(Number);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,7 @@ const accountStatusesController: AppController = async (c) => {
|
||||||
|
|
||||||
const filter: NostrFilter = {
|
const filter: NostrFilter = {
|
||||||
authors: [pubkey],
|
authors: [pubkey],
|
||||||
kinds: [1, 6],
|
kinds: [1, 6, 20],
|
||||||
since,
|
since,
|
||||||
until,
|
until,
|
||||||
limit,
|
limit,
|
||||||
|
|
@ -473,7 +473,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 store.query([{ kinds: [1], ids }], { signal })
|
const events1 = await store.query([{ kinds: [1, 20], ids }], { signal })
|
||||||
.then((events) => hydrateEvents({ events, store, signal }));
|
.then((events) => hydrateEvents({ events, store, signal }));
|
||||||
|
|
||||||
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,7 @@ export const statusZapSplitsController: AppController = async (c) => {
|
||||||
const id = c.req.param('id');
|
const id = c.req.param('id');
|
||||||
const { signal } = c.req.raw;
|
const { signal } = c.req.raw;
|
||||||
|
|
||||||
const [event] = await store.query([{ kinds: [1], ids: [id], limit: 1 }], { signal });
|
const [event] = await store.query([{ kinds: [1, 20], ids: [id], limit: 1 }], { signal });
|
||||||
if (!event) {
|
if (!event) {
|
||||||
return c.json({ error: 'Event not found' }, 404);
|
return c.json({ error: 'Event not found' }, 404);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const reactionController: AppController = async (c) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = await Storages.db();
|
const store = await Storages.db();
|
||||||
const [event] = await store.query([{ kinds: [1], ids: [id], limit: 1 }]);
|
const [event] = await store.query([{ kinds: [1, 20], ids: [id], limit: 1 }]);
|
||||||
|
|
||||||
if (!event) {
|
if (!event) {
|
||||||
return c.json({ error: 'Status not found' }, 404);
|
return c.json({ error: 'Status not found' }, 404);
|
||||||
|
|
@ -56,7 +56,7 @@ const deleteReactionController: AppController = async (c) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const [event] = await store.query([
|
const [event] = await store.query([
|
||||||
{ kinds: [1], ids: [id], limit: 1 },
|
{ kinds: [1, 20], ids: [id], limit: 1 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!event) {
|
if (!event) {
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ async function getLookupFilters({ q, type, resolve }: SearchQuery, signal: Abort
|
||||||
if (n.id().safeParse(q).success) {
|
if (n.id().safeParse(q).success) {
|
||||||
const filters: NostrFilter[] = [];
|
const filters: NostrFilter[] = [];
|
||||||
if (accounts) filters.push({ kinds: [0], authors: [q] });
|
if (accounts) filters.push({ kinds: [0], authors: [q] });
|
||||||
if (statuses) filters.push({ kinds: [1], ids: [q] });
|
if (statuses) filters.push({ kinds: [1, 20], ids: [q] });
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,10 +184,10 @@ async function getLookupFilters({ q, type, resolve }: SearchQuery, signal: Abort
|
||||||
if (accounts) filters.push({ kinds: [0], authors: [result.data.pubkey] });
|
if (accounts) filters.push({ kinds: [0], authors: [result.data.pubkey] });
|
||||||
break;
|
break;
|
||||||
case 'note':
|
case 'note':
|
||||||
if (statuses) filters.push({ kinds: [1], ids: [result.data] });
|
if (statuses) filters.push({ kinds: [1, 20], ids: [result.data] });
|
||||||
break;
|
break;
|
||||||
case 'nevent':
|
case 'nevent':
|
||||||
if (statuses) filters.push({ kinds: [1], ids: [result.data.id] });
|
if (statuses) filters.push({ kinds: [1, 20], ids: [result.data.id] });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return filters;
|
return filters;
|
||||||
|
|
|
||||||
|
|
@ -397,7 +397,7 @@ const unreblogStatusController: AppController = async (c) => {
|
||||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||||
const store = await Storages.db();
|
const store = await Storages.db();
|
||||||
|
|
||||||
const [event] = await store.query([{ ids: [eventId], kinds: [1] }]);
|
const [event] = await store.query([{ ids: [eventId], kinds: [1, 20] }]);
|
||||||
if (!event) {
|
if (!event) {
|
||||||
return c.json({ error: 'Record not found' }, 404);
|
return c.json({ error: 'Record not found' }, 404);
|
||||||
}
|
}
|
||||||
|
|
@ -429,13 +429,13 @@ const quotesController: AppController = async (c) => {
|
||||||
const params = c.get('pagination');
|
const params = c.get('pagination');
|
||||||
const store = await Storages.db();
|
const store = await Storages.db();
|
||||||
|
|
||||||
const [event] = await store.query([{ ids: [id], kinds: [1] }]);
|
const [event] = await store.query([{ ids: [id], kinds: [1, 20] }]);
|
||||||
if (!event) {
|
if (!event) {
|
||||||
return c.json({ error: 'Event not found.' }, 404);
|
return c.json({ error: 'Event not found.' }, 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
const quotes = await store
|
const quotes = await store
|
||||||
.query([{ kinds: [1], '#q': [event.id], ...params }])
|
.query([{ kinds: [1, 20], '#q': [event.id], ...params }])
|
||||||
.then((events) => hydrateEvents({ events, store }));
|
.then((events) => hydrateEvents({ events, store }));
|
||||||
|
|
||||||
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
||||||
|
|
|
||||||
|
|
@ -214,20 +214,20 @@ async function topicToFilter(
|
||||||
|
|
||||||
switch (topic) {
|
switch (topic) {
|
||||||
case 'public':
|
case 'public':
|
||||||
return { kinds: [1, 6] };
|
return { kinds: [1, 6, 20] };
|
||||||
case 'public:local':
|
case 'public:local':
|
||||||
return { kinds: [1, 6], search: `domain:${host}` };
|
return { kinds: [1, 6, 20], search: `domain:${host}` };
|
||||||
case 'hashtag':
|
case 'hashtag':
|
||||||
if (query.tag) return { kinds: [1, 6], '#t': [query.tag] };
|
if (query.tag) return { kinds: [1, 6, 20], '#t': [query.tag] };
|
||||||
break;
|
break;
|
||||||
case 'hashtag:local':
|
case 'hashtag:local':
|
||||||
if (query.tag) return { kinds: [1, 6], '#t': [query.tag], search: `domain:${host}` };
|
if (query.tag) return { kinds: [1, 6, 20], '#t': [query.tag], search: `domain:${host}` };
|
||||||
break;
|
break;
|
||||||
case 'user':
|
case 'user':
|
||||||
// HACK: this puts the user's entire contacts list into RAM,
|
// HACK: this puts the user's entire contacts list into RAM,
|
||||||
// and then calls `matchFilters` over it. Refreshing the page
|
// and then calls `matchFilters` over it. Refreshing the page
|
||||||
// is required after following a new user.
|
// is required after following a new user.
|
||||||
return pubkey ? { kinds: [1, 6], authors: [...await getFeedPubkeys(pubkey)] } : undefined;
|
return pubkey ? { kinds: [1, 6, 20], authors: [...await getFeedPubkeys(pubkey)] } : undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ const homeTimelineController: AppController = async (c) => {
|
||||||
const params = c.get('pagination');
|
const params = c.get('pagination');
|
||||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||||
const authors = [...await getFeedPubkeys(pubkey)];
|
const authors = [...await getFeedPubkeys(pubkey)];
|
||||||
return renderStatuses(c, [{ authors, kinds: [1, 6], ...params }]);
|
return renderStatuses(c, [{ authors, kinds: [1, 6, 20], ...params }]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const publicQuerySchema = z.object({
|
const publicQuerySchema = z.object({
|
||||||
|
|
@ -33,7 +33,7 @@ const publicTimelineController: AppController = (c) => {
|
||||||
|
|
||||||
const { local, instance, language } = result.data;
|
const { local, instance, language } = result.data;
|
||||||
|
|
||||||
const filter: NostrFilter = { kinds: [1], ...params };
|
const filter: NostrFilter = { kinds: [1, 20], ...params };
|
||||||
|
|
||||||
const search: `${string}:${string}`[] = [];
|
const search: `${string}:${string}`[] = [];
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ const publicTimelineController: AppController = (c) => {
|
||||||
const hashtagTimelineController: AppController = (c) => {
|
const hashtagTimelineController: AppController = (c) => {
|
||||||
const hashtag = c.req.param('hashtag')!.toLowerCase();
|
const hashtag = c.req.param('hashtag')!.toLowerCase();
|
||||||
const params = c.get('pagination');
|
const params = c.get('pagination');
|
||||||
return renderStatuses(c, [{ kinds: [1], '#t': [hashtag], ...params }]);
|
return renderStatuses(c, [{ kinds: [1, 20], '#t': [hashtag], ...params }]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const suggestedTimelineController: AppController = async (c) => {
|
const suggestedTimelineController: AppController = async (c) => {
|
||||||
|
|
@ -70,7 +70,7 @@ const suggestedTimelineController: AppController = async (c) => {
|
||||||
|
|
||||||
const authors = [...getTagSet(follows?.tags ?? [], 'p')];
|
const authors = [...getTagSet(follows?.tags ?? [], 'p')];
|
||||||
|
|
||||||
return renderStatuses(c, [{ authors, kinds: [1], ...params }]);
|
return renderStatuses(c, [{ authors, kinds: [1, 20], ...params }]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Render statuses for timelines. */
|
/** Render statuses for timelines. */
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ const trendingStatusesController: AppController = async (c) => {
|
||||||
return c.json([]);
|
return c.json([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await store.query([{ kinds: [1], ids }])
|
const results = await store.query([{ kinds: [1, 20], ids }])
|
||||||
.then((events) => hydrateEvents({ events, store }));
|
.then((events) => hydrateEvents({ events, store }));
|
||||||
|
|
||||||
// Sort events in the order they appear in the label.
|
// Sort events in the order they appear in the label.
|
||||||
|
|
|
||||||
|
|
@ -102,21 +102,21 @@ export function assembleEvents(
|
||||||
if (event.kind === 1) {
|
if (event.kind === 1) {
|
||||||
const id = findQuoteTag(event.tags)?.[1] || findQuoteInContent(event.content);
|
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, 20], ids: [id] }, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.kind === 6) {
|
if (event.kind === 6) {
|
||||||
const id = event.tags.find(([name]) => name === 'e')?.[1];
|
const id = event.tags.find(([name]) => name === 'e')?.[1];
|
||||||
if (id) {
|
if (id) {
|
||||||
event.repost = b.find((e) => matchFilter({ kinds: [1], ids: [id] }, e));
|
event.repost = b.find((e) => matchFilter({ kinds: [1, 20], ids: [id] }, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.kind === 7) {
|
if (event.kind === 7) {
|
||||||
const id = event.tags.findLast(([name]) => name === 'e')?.[1];
|
const id = event.tags.findLast(([name]) => name === 'e')?.[1];
|
||||||
if (id) {
|
if (id) {
|
||||||
event.reacted = b.find((e) => matchFilter({ kinds: [1], ids: [id] }, e));
|
event.reacted = b.find((e) => matchFilter({ kinds: [1, 20], ids: [id] }, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +130,7 @@ export function assembleEvents(
|
||||||
const ids = event.tags.filter(([name]) => name === 'e').map(([_name, value]) => value);
|
const ids = event.tags.filter(([name]) => name === 'e').map(([_name, value]) => value);
|
||||||
|
|
||||||
for (const id of ids) {
|
for (const id of ids) {
|
||||||
const reported = b.find((e) => matchFilter({ kinds: [1], ids: [id] }, e));
|
const reported = b.find((e) => matchFilter({ kinds: [1, 20], ids: [id] }, e));
|
||||||
if (reported) {
|
if (reported) {
|
||||||
reportedEvents.push(reported);
|
reportedEvents.push(reported);
|
||||||
}
|
}
|
||||||
|
|
@ -146,7 +146,7 @@ export function assembleEvents(
|
||||||
|
|
||||||
const id = event.tags.find(([name]) => name === 'e')?.[1];
|
const id = event.tags.find(([name]) => name === 'e')?.[1];
|
||||||
if (id) {
|
if (id) {
|
||||||
event.zapped = b.find((e) => matchFilter({ kinds: [1], ids: [id] }, e));
|
event.zapped = b.find((e) => matchFilter({ kinds: [1, 20], ids: [id] }, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
const zapRequestString = event?.tags?.find(([name]) => name === 'description')?.[1];
|
const zapRequestString = event?.tags?.find(([name]) => name === 'description')?.[1];
|
||||||
|
|
@ -313,7 +313,7 @@ function gatherReportedNotes({ events, store, signal }: HydrateOpts): Promise<Di
|
||||||
}
|
}
|
||||||
|
|
||||||
return store.query(
|
return store.query(
|
||||||
[{ kinds: [1], ids: [...ids], limit: ids.size }],
|
[{ kinds: [1, 20], ids: [...ids], limit: ids.size }],
|
||||||
{ signal },
|
{ signal },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ export async function countAuthorStats(
|
||||||
): Promise<DittoTables['author_stats']> {
|
): Promise<DittoTables['author_stats']> {
|
||||||
const [{ count: followers_count }, { count: notes_count }, [followList], [kind0]] = await Promise.all([
|
const [{ count: followers_count }, { count: notes_count }, [followList], [kind0]] = await Promise.all([
|
||||||
store.count([{ kinds: [3], '#p': [pubkey] }]),
|
store.count([{ kinds: [3], '#p': [pubkey] }]),
|
||||||
store.count([{ kinds: [1], authors: [pubkey] }]),
|
store.count([{ kinds: [1, 20], authors: [pubkey] }]),
|
||||||
store.query([{ kinds: [3], authors: [pubkey], limit: 1 }]),
|
store.query([{ kinds: [3], authors: [pubkey], limit: 1 }]),
|
||||||
store.query([{ kinds: [0], authors: [pubkey], limit: 1 }]),
|
store.query([{ kinds: [0], authors: [pubkey], limit: 1 }]),
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ async function renderStatuses(c: AppContext, ids: string[], signal = AbortSignal
|
||||||
const store = await Storages.db();
|
const store = await Storages.db();
|
||||||
const { limit } = c.get('pagination');
|
const { limit } = c.get('pagination');
|
||||||
|
|
||||||
const events = await store.query([{ kinds: [1], ids, limit }], { signal })
|
const events = await store.query([{ kinds: [1, 20], ids, limit }], { signal })
|
||||||
.then((events) => hydrateEvents({ events, store, signal }));
|
.then((events) => hydrateEvents({ events, store, signal }));
|
||||||
|
|
||||||
if (!events.length) {
|
if (!events.length) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue