From 3ac3e11d3c998f365c86145e34948f9beb34f210 Mon Sep 17 00:00:00 2001 From: Jure <44338+hoornet@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:33:34 +0200 Subject: [PATCH] Fix search: independent relay queries, nostr: URI prefix, add nostr.wine --- src/components/search/SearchView.tsx | 3 +- src/lib/nostr/search.ts | 49 ++++++++++++++++++---------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/components/search/SearchView.tsx b/src/components/search/SearchView.tsx index acf392f..05f73b5 100644 --- a/src/components/search/SearchView.tsx +++ b/src/components/search/SearchView.tsx @@ -199,7 +199,8 @@ export function SearchView() { }, []); const handleSearch = async (overrideQuery?: string) => { - const q = (overrideQuery ?? query).trim(); + // Strip nostr: URI prefix (NIP-21) so pasted share links work + const q = (overrideQuery ?? query).trim().replace(/^nostr:/i, ""); if (!q) return; if (overrideQuery) setQuery(overrideQuery); diff --git a/src/lib/nostr/search.ts b/src/lib/nostr/search.ts index 8ffa42a..7ab29f8 100644 --- a/src/lib/nostr/search.ts +++ b/src/lib/nostr/search.ts @@ -6,33 +6,46 @@ import { getNDK, fetchWithTimeout, withTimeout, FEED_TIMEOUT } from "./core"; const SEARCH_RELAYS = [ "wss://relay.nostr.band", "wss://search.nos.today", + "wss://nostr.wine", ]; -// Persistent NDK instance dedicated to search relays — stays connected -let searchNDK: NDK | null = null; -let searchNDKConnecting: Promise | null = null; +// One persistent NDK per search relay — queried independently so a slow/dead +// relay can't block results from the others. +const searchNDKs: Map = new Map(); -async function getSearchNDK(): Promise { - if (searchNDK) return searchNDK; - searchNDK = new NDK({ explicitRelayUrls: SEARCH_RELAYS }); - searchNDKConnecting = searchNDK.connect().then(() => { - console.log("[Vega] Search relays connected"); - searchNDKConnecting = null; - }); - await withTimeout(searchNDKConnecting, 5000, undefined); - return searchNDK; +async function getSearchNDKFor(relay: string): Promise { + let ndk = searchNDKs.get(relay); + if (ndk) return ndk; + ndk = new NDK({ explicitRelayUrls: [relay] }); + searchNDKs.set(relay, ndk); + await withTimeout(ndk.connect(), 5000, undefined); + console.log(`[Vega] Search relay connected: ${relay}`); + return ndk; } const EMPTY_SET = new Set(); -/** Fetch events from the dedicated search relays with timeout. */ +/** Fetch events from all search relays independently, merge results. */ async function searchFetch(filter: NDKFilter, timeoutMs = FEED_TIMEOUT): Promise> { - const ndk = await getSearchNDK(); - const promise = ndk.fetchEvents(filter, { - cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY, - groupable: false, + const perRelay = SEARCH_RELAYS.map(async (relay) => { + try { + const ndk = await getSearchNDKFor(relay); + const events = await withTimeout( + ndk.fetchEvents(filter, { cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY, groupable: false }), + timeoutMs, + EMPTY_SET, + ); + return events; + } catch { + return EMPTY_SET; + } }); - return withTimeout(promise, timeoutMs, EMPTY_SET); + const results = await Promise.all(perRelay); + const merged = new Set(); + for (const set of results) { + for (const e of set) merged.add(e); + } + return merged; } export async function searchNotes(query: string, limit = 50): Promise {