diff --git a/src/api/accounts.ts b/src/api/accounts.ts index e12b1aa..2377aa3 100644 --- a/src/api/accounts.ts +++ b/src/api/accounts.ts @@ -1,9 +1,12 @@ import { type AppController } from '@/app.ts'; +import { nip05 } from '@/deps.ts'; import { getAuthor } from '../client.ts'; import { toAccount } from '../transmute.ts'; import { bech32ToPubkey } from '../utils.ts'; +import type { Event } from '../event.ts'; + const credentialsController: AppController = async (c) => { const pubkey = c.get('pubkey')!; @@ -33,17 +36,9 @@ const accountLookupController: AppController = async (c) => { return c.json({ error: 'Missing `acct` query parameter.' }, 422); } - if (acct.includes('@')) { - // TODO: NIP-05 handling - return c.json({ error: 'NIP-05 lookups not yet implemented.' }, 422); - } - - const pubkey = bech32ToPubkey(acct); - if (pubkey) { - const event = await getAuthor(pubkey); - if (event) { - return c.json(toAccount(event)); - } + const event = await lookupAccount(acct); + if (event) { + return c.json(toAccount(event)); } return c.json({ error: 'Could not find user.' }, 404); @@ -56,15 +51,23 @@ const accountSearchController: AppController = async (c) => { return c.json({ error: 'Missing `q` query parameter.' }, 422); } - const pubkey = bech32ToPubkey(q); - if (pubkey) { - const event = await getAuthor(pubkey); - if (event) { - return c.json([toAccount(event)]); - } + const event = await lookupAccount(decodeURIComponent(q)); + if (event) { + return c.json([toAccount(event)]); } return c.json([]); }; +/** Resolve a bech32 or NIP-05 identifier to an account. */ +async function lookupAccount(value: string): Promise | undefined> { + console.log(`Looking up ${value}`); + + const pubkey = bech32ToPubkey(value) || (await nip05.queryProfile(value))?.pubkey; + + if (pubkey) { + return getAuthor(pubkey); + } +} + export { accountController, accountLookupController, accountSearchController, credentialsController }; diff --git a/src/client.ts b/src/client.ts index a2448f7..bf30a49 100644 --- a/src/client.ts +++ b/src/client.ts @@ -8,26 +8,26 @@ import { eventDateComparator, nostrNow } from './utils.ts'; const pool = new RelayPool(poolRelays); /** Get a Nostr event by its ID. */ -const getEvent = async (id: string): Promise => { +const getEvent = async (id: string): Promise => { const event = await (pool.getEventById(id, poolRelays, 0) as Promise); - return event?.id === id ? event : null; + return event?.id === id ? event : undefined; }; /** Get a Nostr `set_medatadata` event for a user's pubkey. */ -const getAuthor = async (pubkey: string): Promise | null> => { +const getAuthor = async (pubkey: string): Promise | undefined> => { const author = new Author(pool, poolRelays, pubkey); const event: SignedEvent<0> | null = await new Promise((resolve) => author.metaData(resolve, 0)); - return event?.pubkey === pubkey ? event : null; + return event?.pubkey === pubkey ? event : undefined; }; /** Get users the given pubkey follows. */ -const getFollows = (pubkey: string): Promise | null> => { +const getFollows = (pubkey: string): Promise | undefined> => { return new Promise((resolve) => { pool.subscribe( [{ authors: [pubkey], kinds: [3] }], poolRelays, (event: SignedEvent<3> | null) => { - resolve(event?.pubkey === pubkey ? event : null); + resolve(event?.pubkey === pubkey ? event : undefined); }, undefined, undefined, diff --git a/src/deps.ts b/src/deps.ts index e12e028..08817db 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -14,6 +14,7 @@ export { type Filter, getEventHash, getPublicKey, + nip05, nip19, nip21, signEvent as getSignature,