diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c9c9588..08db0c2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: denoland/deno:2.0.1 +image: denoland/deno:2.0.2 default: interruptible: true @@ -35,5 +35,4 @@ test: paths: - deno-test.xml reports: - junit: deno-test.xml - + junit: deno-test.xml \ No newline at end of file diff --git a/.tool-versions b/.tool-versions index e0a5703..b6f353e 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -deno 2.0.1 \ No newline at end of file +deno 2.0.2 \ No newline at end of file diff --git a/src/controllers/api/statuses.ts b/src/controllers/api/statuses.ts index 1990789..e32509c 100644 --- a/src/controllers/api/statuses.ts +++ b/src/controllers/api/statuses.ts @@ -560,7 +560,7 @@ const zapController: AppController = async (c) => { lnurl = getLnurl(meta); if (target && lnurl) { tags.push( - ['e', target.id, Conf.relay, '', target.pubkey], + ['e', target.id, Conf.relay], ['p', target.pubkey, Conf.relay], ['amount', amount.toString()], ['relays', Conf.relay], diff --git a/src/queries.ts b/src/queries.ts index 3ca805a..e93027d 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -6,6 +6,7 @@ import { Storages } from '@/storages.ts'; import { type DittoEvent } from '@/interfaces/DittoEvent.ts'; import { type DittoRelation } from '@/interfaces/DittoFilter.ts'; import { hydrateEvents } from '@/storages/hydrate.ts'; +import { fallbackAuthor } from '@/utils.ts'; import { findReplyTag, getTagSet } from '@/utils/tags.ts'; const debug = Debug('ditto:queries'); @@ -38,15 +39,21 @@ const getEvent = async ( .then(([event]) => event); }; -/** Get a Nostr `set_medatadata` event for a user's pubkey. */ -const getAuthor = async (pubkey: string, opts: GetEventOpts = {}): Promise => { +/** + * Get a Nostr `set_medatadata` event for a user's pubkey. + * @deprecated Use `store.query` directly. + */ +async function getAuthor(pubkey: string, opts: GetEventOpts = {}): Promise { const store = await Storages.db(); const { signal = AbortSignal.timeout(1000) } = opts; - return await store.query([{ authors: [pubkey], kinds: [0], limit: 1 }], { limit: 1, signal }) - .then((events) => hydrateEvents({ events, store, signal })) - .then(([event]) => event); -}; + const events = await store.query([{ authors: [pubkey], kinds: [0], limit: 1 }], { limit: 1, signal }); + const event = events[0] ?? fallbackAuthor(pubkey); + + await hydrateEvents({ events: [event], store, signal }); + + return event; +} /** Get users the given pubkey follows. */ const getFollows = async (pubkey: string, signal?: AbortSignal): Promise => { diff --git a/src/storages/hydrate.ts b/src/storages/hydrate.ts index ea2d8da..522eb20 100644 --- a/src/storages/hydrate.ts +++ b/src/storages/hydrate.ts @@ -7,6 +7,7 @@ import { z } from 'zod'; import { DittoTables } from '@/db/DittoTables.ts'; import { Conf } from '@/config.ts'; import { type DittoEvent } from '@/interfaces/DittoEvent.ts'; +import { fallbackAuthor } from '@/utils.ts'; import { findQuoteTag } from '@/utils/tags.ts'; import { findQuoteInContent } from '@/utils/note.ts'; import { getAmount } from '@/utils/bolt11.ts'; @@ -225,6 +226,7 @@ function gatherQuotes({ events, store, signal }: HydrateOpts): Promise { const pubkeys = new Set(); @@ -247,10 +249,20 @@ function gatherAuthors({ events, store, signal }: HydrateOpts): Promise matchFilter({ kinds: [0], authors: [pubkey] }, e)); + if (author) { + const fallback = fallbackAuthor(pubkey); + authors.push(fallback); + } + } + + return authors; } /** Collect users from the events. */ diff --git a/src/utils.ts b/src/utils.ts index ae25737..a1298de 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -74,6 +74,30 @@ function isURL(value: unknown): boolean { return z.string().url().safeParse(value).success; } -export { bech32ToPubkey, eventAge, findTag, isNostrId, isURL, type Nip05, nostrDate, nostrNow, parseNip05 }; +/** Render an empty author event so other things can stick to it. */ +function fallbackAuthor(pubkey: string): NostrEvent { + return { + kind: 0, + pubkey, + content: '', + tags: [], + created_at: nostrNow(), + id: '', + sig: '', + }; +} + +export { + bech32ToPubkey, + eventAge, + fallbackAuthor, + findTag, + isNostrId, + isURL, + type Nip05, + nostrDate, + nostrNow, + parseNip05, +}; export { Time } from '@/utils/time.ts';