From 8f5ec50a25594d17b44ccb9182384051db6e4763 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 7 Aug 2024 16:41:46 -0500 Subject: [PATCH] search: fix nip05 lookups --- src/controllers/api/search.ts | 77 ++++++++++++++++++----------------- src/utils/lookup.ts | 9 ++-- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/controllers/api/search.ts b/src/controllers/api/search.ts index ef7f84c7..23eba60f 100644 --- a/src/controllers/api/search.ts +++ b/src/controllers/api/search.ts @@ -6,8 +6,7 @@ import { AppController } from '@/app.ts'; import { booleanParamSchema } from '@/schema.ts'; import { Storages } from '@/storages.ts'; import { hydrateEvents } from '@/storages/hydrate.ts'; -import { bech32ToPubkey } from '@/utils.ts'; -import { ACCT_REGEX, extractIdentifier } from '@/utils/lookup.ts'; +import { extractIdentifier, lookupPubkey } from '@/utils/lookup.ts'; import { nip05Cache } from '@/utils/nip05.ts'; import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts'; import { renderStatus } from '@/views/mastodon/statuses.ts'; @@ -36,7 +35,7 @@ const searchController: AppController = async (c) => { // Render account from pubkey. if (!event && lookup) { - const pubkey = bech32ToPubkey(lookup); + const pubkey = await lookupPubkey(lookup); return c.json({ accounts: pubkey ? [await accountFromPubkey(pubkey)] : [], statuses: [], @@ -120,51 +119,55 @@ async function lookupEvent(query: SearchQuery, signal: AbortSignal): Promise { - const filters: NostrFilter[] = []; - const accounts = !type || type === 'accounts'; const statuses = !type || type === 'statuses'; if (!resolve || type === 'hashtags') { + return []; + } + + if (n.id().safeParse(q).success) { + const filters: NostrFilter[] = []; + if (accounts) filters.push({ kinds: [0], authors: [q] }); + if (statuses) filters.push({ kinds: [1], ids: [q] }); return filters; } const lookup = extractIdentifier(q); - if (lookup) { - try { - const result = nip19.decode(lookup); - switch (result.type) { - case 'npub': - if (accounts) filters.push({ kinds: [0], authors: [result.data] }); - break; - case 'nprofile': - if (accounts) filters.push({ kinds: [0], authors: [result.data.pubkey] }); - break; - case 'note': - if (statuses) filters.push({ kinds: [1], ids: [result.data] }); - break; - case 'nevent': - if (statuses) filters.push({ kinds: [1], ids: [result.data.id] }); - break; - } - } catch { - // do nothing - } - } else if (n.id().safeParse(q).success) { - if (accounts) filters.push({ kinds: [0], authors: [q] }); - if (statuses) filters.push({ kinds: [1], ids: [q] }); - } else if (accounts && ACCT_REGEX.test(q)) { - try { - const { pubkey } = await nip05Cache.fetch(q, { signal }); - if (pubkey) { - filters.push({ kinds: [0], authors: [pubkey] }); - } - } catch { - // do nothing + if (!lookup) return []; + + try { + const result = nip19.decode(lookup); + const filters: NostrFilter[] = []; + switch (result.type) { + case 'npub': + if (accounts) filters.push({ kinds: [0], authors: [result.data] }); + break; + case 'nprofile': + if (accounts) filters.push({ kinds: [0], authors: [result.data.pubkey] }); + break; + case 'note': + if (statuses) filters.push({ kinds: [1], ids: [result.data] }); + break; + case 'nevent': + if (statuses) filters.push({ kinds: [1], ids: [result.data.id] }); + break; } + return filters; + } catch { + // do nothing } - return filters; + try { + const { pubkey } = await nip05Cache.fetch(lookup, { signal }); + if (pubkey) { + return [{ kinds: [0], authors: [pubkey] }]; + } + } catch { + // do nothing + } + + return []; } export { searchController }; diff --git a/src/utils/lookup.ts b/src/utils/lookup.ts index afcd384d..a824949a 100644 --- a/src/utils/lookup.ts +++ b/src/utils/lookup.ts @@ -7,9 +7,6 @@ import { bech32ToPubkey } from '@/utils.ts'; import { nip05Cache } from '@/utils/nip05.ts'; import { Stickynotes } from '@soapbox/stickynotes'; -/** Matches NIP-05 names with or without an @ in front. */ -export const ACCT_REGEX = /^@?(?:([\w.+-]+)@)?([\w.-]+)$/; - /** Resolve a bech32 or NIP-05 identifier to an account. */ export async function lookupAccount( value: string, @@ -43,6 +40,8 @@ export async function lookupPubkey(value: string, signal?: AbortSignal): Promise /** Extract an acct or bech32 identifier out of a URL or of itself. */ export function extractIdentifier(value: string): string | undefined { + value = value.trim(); + try { const uri = new URL(value); switch (uri.protocol) { @@ -79,11 +78,13 @@ export function extractIdentifier(value: string): string | undefined { // do nothing } + value = value.replace(/^@/, ''); + if (n.bech32().safeParse(value).success) { return value; } - if (ACCT_REGEX.test(value)) { + if (NIP05.regex().test(value)) { return value; } }