From b7ec1fcf0692f7a8c1ce1c37cb531830224299b3 Mon Sep 17 00:00:00 2001 From: Gigi Date: Fri, 17 Oct 2025 20:42:46 +0200 Subject: [PATCH] fix: add 5s timeout and smart encryption detection for bookmarks Changes: - Use 5-second timeout instead of 30 seconds - Detect encryption method from content format - NIP-04 has '?iv=' in content, NIP-44 doesn't - Try the likely method first to avoid unnecessary timeouts - Falls back to other method if first fails This should: - Prevent hanging forever (5s timeout) - Be much faster than 30s when wrong method is tried - Usually decrypt instantly when right method is used first --- src/services/bookmarkProcessing.ts | 31 ++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/services/bookmarkProcessing.ts b/src/services/bookmarkProcessing.ts index d47557e7..7d9ce059 100644 --- a/src/services/bookmarkProcessing.ts +++ b/src/services/bookmarkProcessing.ts @@ -5,7 +5,7 @@ import { } from '../types/bookmarks' import { BookmarkHiddenSymbol, hasNip04Decrypt, hasNip44Decrypt, processApplesauceBookmarks } from './bookmarkHelpers' import type { NostrEvent } from './bookmarkHelpers' -import { mapWithConcurrency } from '../utils/async' +import { mapWithConcurrency, withTimeout } from '../utils/async' type DecryptFn = (pubkey: string, content: string) => Promise type UnlockHiddenTagsFn = typeof Helpers.unlockHiddenTags @@ -37,19 +37,30 @@ async function decryptEvent( } } else if (evt.content && evt.content.length > 0) { let decryptedContent: string | undefined - try { - if (hasNip44Decrypt(signerCandidate)) { - decryptedContent = await (signerCandidate as { nip44: { decrypt: DecryptFn } }).nip44.decrypt(evt.pubkey, evt.content) + + // Try to detect encryption method from content format + // NIP-44 starts with version byte (currently 0x02), NIP-04 is base64 + const looksLikeNip44 = evt.content.length > 0 && !evt.content.includes('?iv=') + + // Try the likely method first, with a 5s timeout + if (looksLikeNip44 && hasNip44Decrypt(signerCandidate)) { + try { + decryptedContent = await withTimeout( + (signerCandidate as { nip44: { decrypt: DecryptFn } }).nip44.decrypt(evt.pubkey, evt.content), + 5000 + ) + } catch (err) { + console.log("[bunker] ❌ nip44.decrypt failed:", err instanceof Error ? err.message : String(err)) } - } catch (err) { - console.log("[bunker] ❌ nip44.decrypt failed:", err instanceof Error ? err.message : String(err)) } - if (!decryptedContent) { + // Fallback to nip04 if nip44 failed or content looks like nip04 + if (!decryptedContent && hasNip04Decrypt(signerCandidate)) { try { - if (hasNip04Decrypt(signerCandidate)) { - decryptedContent = await (signerCandidate as { nip04: { decrypt: DecryptFn } }).nip04.decrypt(evt.pubkey, evt.content) - } + decryptedContent = await withTimeout( + (signerCandidate as { nip04: { decrypt: DecryptFn } }).nip04.decrypt(evt.pubkey, evt.content), + 5000 + ) } catch (err) { console.log("[bunker] ❌ nip04.decrypt failed:", err instanceof Error ? err.message : String(err)) }