diff --git a/src/lib/components/Preview.svelte b/src/lib/components/Preview.svelte index 30b7f10..0c85484 100644 --- a/src/lib/components/Preview.svelte +++ b/src/lib/components/Preview.svelte @@ -1,6 +1,6 @@ - + diff --git a/src/lib/components/util/Profile.svelte b/src/lib/components/util/Profile.svelte index fd23c9f..6918677 100644 --- a/src/lib/components/util/Profile.svelte +++ b/src/lib/components/util/Profile.svelte @@ -70,25 +70,21 @@ function shortenNpub(long: string|undefined) { {#if isNav}
  • - Sign out - +
  • {:else} {/if} diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 021c979..35d6e03 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -10,6 +10,20 @@ export function neventEncode(event: NDKEvent, relays: string[]) { }); } +export function naddrEncode(event: NDKEvent, relays: string[]) { + const dTag = event.getMatchingTags('d')[0]?.[1]; + if (!dTag) { + throw new Error('Event does not have a d tag'); + } + + return nip19.naddrEncode({ + identifier: dTag, + pubkey: event.pubkey, + kind: event.kind || 0, + relays, + }); +} + export function formatDate(unixtimestamp: number) { const months = [ "Jan", diff --git a/src/routes/publication/+page.ts b/src/routes/publication/+page.ts index 7fddcdc..286063a 100644 --- a/src/routes/publication/+page.ts +++ b/src/routes/publication/+page.ts @@ -1,48 +1,104 @@ import { error } from '@sveltejs/kit'; import type { NDKEvent } from '@nostr-dev-kit/ndk'; import type { PageLoad } from './$types'; +import { nip19 } from 'nostr-tools'; import { getActiveRelays } from '$lib/ndk.ts'; -import { setContext } from 'svelte'; -import { PublicationTree } from '$lib/data_structures/publication_tree.ts'; + +/** + * Decodes an naddr identifier and returns a filter object + */ +function decodeNaddr(id: string) { + try { + if (!id.startsWith('naddr')) return {}; + + const decoded = nip19.decode(id); + if (decoded.type !== 'naddr') return {}; + + const data = decoded.data; + return { + kinds: [data.kind], + authors: [data.pubkey], + '#d': [data.identifier] + }; + } catch (e) { + console.error('Failed to decode naddr:', e); + return null; + } +} + +/** + * Fetches an event by ID or filter + */ +async function fetchEventById(ndk: any, id: string): Promise { + const filter = decodeNaddr(id); + + // Handle the case where filter is null (decoding error) + if (filter === null) { + // If we can't decode the naddr, try using the raw ID + try { + const event = await ndk.fetchEvent(id); + if (!event) { + throw new Error(`Event not found for ID: ${id}`); + } + return event; + } catch (err) { + throw error(404, `Failed to fetch publication root event.\n${err}`); + } + } + + const hasFilter = Object.keys(filter).length > 0; + + try { + const event = await (hasFilter ? + ndk.fetchEvent(filter) : + ndk.fetchEvent(id)); + + if (!event) { + throw new Error(`Event not found for ID: ${id}`); + } + return event; + } catch (err) { + throw error(404, `Failed to fetch publication root event.\n${err}`); + } +} + +/** + * Fetches an event by d tag + */ +async function fetchEventByDTag(ndk: any, dTag: string): Promise { + try { + const event = await ndk.fetchEvent( + { '#d': [dTag] }, + { closeOnEose: false }, + getActiveRelays(ndk) + ); + + if (!event) { + throw new Error(`Event not found for d tag: ${dTag}`); + } + return event; + } catch (err) { + throw error(404, `Failed to fetch publication root event.\n${err}`); + } +} export const load: PageLoad = async ({ url, parent }: { url: URL; parent: () => Promise }) => { const id = url.searchParams.get('id'); const dTag = url.searchParams.get('d'); - const { ndk, parser } = await parent(); - - let eventPromise: Promise; - let indexEvent: NDKEvent | null; - - if (id) { - eventPromise = ndk.fetchEvent(id) - .then((ev: NDKEvent | null) => { - return ev; - }) - .catch((err: any) => { - error(404, `Failed to fetch publication root event for ID: ${id}\n${err}`); - }); - } else if (dTag) { - eventPromise = new Promise(resolve => { - ndk - .fetchEvent({ '#d': [dTag] }, { closeOnEose: false }, getActiveRelays(ndk)) - .then((event: NDKEvent | null) => { - resolve(event); - }) - .catch((err: any) => { - error(404, `Failed to fetch publication root event for d tag: ${dTag}\n${err}`); - }); - }); - } else { - error(400, 'No publication root event ID or d tag provided.'); + + if (!id && !dTag) { + throw error(400, 'No publication root event ID or d tag provided.'); } - - indexEvent = await eventPromise as NDKEvent; + + // Fetch the event based on available parameters + const indexEvent = id + ? await fetchEventById(ndk, id) + : await fetchEventByDTag(ndk, dTag!); + const publicationType = indexEvent?.getMatchingTags('type')[0]?.[1]; const fetchPromise = parser.fetch(indexEvent); - setContext('publicationTree', new PublicationTree(indexEvent, ndk)); - return { waitable: fetchPromise, publicationType,