Fix search: independent relay queries, nostr: URI prefix, add nostr.wine

This commit is contained in:
Jure
2026-03-31 06:33:34 +02:00
parent 6a7a0bccf3
commit 3ac3e11d3c
2 changed files with 33 additions and 19 deletions

View File

@@ -199,7 +199,8 @@ export function SearchView() {
}, []); }, []);
const handleSearch = async (overrideQuery?: string) => { 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 (!q) return;
if (overrideQuery) setQuery(overrideQuery); if (overrideQuery) setQuery(overrideQuery);

View File

@@ -6,33 +6,46 @@ import { getNDK, fetchWithTimeout, withTimeout, FEED_TIMEOUT } from "./core";
const SEARCH_RELAYS = [ const SEARCH_RELAYS = [
"wss://relay.nostr.band", "wss://relay.nostr.band",
"wss://search.nos.today", "wss://search.nos.today",
"wss://nostr.wine",
]; ];
// Persistent NDK instance dedicated to search relaysstays connected // One persistent NDK per search relay — queried independently so a slow/dead
let searchNDK: NDK | null = null; // relay can't block results from the others.
let searchNDKConnecting: Promise<void> | null = null; const searchNDKs: Map<string, NDK> = new Map();
async function getSearchNDK(): Promise<NDK> { async function getSearchNDKFor(relay: string): Promise<NDK> {
if (searchNDK) return searchNDK; let ndk = searchNDKs.get(relay);
searchNDK = new NDK({ explicitRelayUrls: SEARCH_RELAYS }); if (ndk) return ndk;
searchNDKConnecting = searchNDK.connect().then(() => { ndk = new NDK({ explicitRelayUrls: [relay] });
console.log("[Vega] Search relays connected"); searchNDKs.set(relay, ndk);
searchNDKConnecting = null; await withTimeout(ndk.connect(), 5000, undefined);
}); console.log(`[Vega] Search relay connected: ${relay}`);
await withTimeout(searchNDKConnecting, 5000, undefined); return ndk;
return searchNDK;
} }
const EMPTY_SET = new Set<NDKEvent>(); const EMPTY_SET = new Set<NDKEvent>();
/** 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<Set<NDKEvent>> { async function searchFetch(filter: NDKFilter, timeoutMs = FEED_TIMEOUT): Promise<Set<NDKEvent>> {
const ndk = await getSearchNDK(); const perRelay = SEARCH_RELAYS.map(async (relay) => {
const promise = ndk.fetchEvents(filter, { try {
cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY, const ndk = await getSearchNDKFor(relay);
groupable: false, 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<NDKEvent>();
for (const set of results) {
for (const e of set) merged.add(e);
}
return merged;
} }
export async function searchNotes(query: string, limit = 50): Promise<NDKEvent[]> { export async function searchNotes(query: string, limit = 50): Promise<NDKEvent[]> {