Browse Source

bug-fix

imwald
Silberengel 2 weeks ago
parent
commit
eaa83d8e37
  1. 6
      src/components/SearchBar/index.tsx
  2. 24
      src/lib/url-relay-input.test.ts
  3. 16
      src/lib/url.ts

6
src/components/SearchBar/index.tsx

@ -4,7 +4,7 @@ import { toNote, toNoteList } from '@/lib/link' @@ -4,7 +4,7 @@ import { toNote, toNoteList } from '@/lib/link'
import client from '@/services/client.service'
import { eventService } from '@/services/client.service'
import { randomString } from '@/lib/random'
import { isKind10243HttpRelayTagUrl, isWebsocketUrl, looksLikeNostrBech32Identifier, normalizeAnyRelayUrl, normalizeHttpRelayUrl } from '@/lib/url'
import { isKind10243HttpRelayTagUrl, isWebsocketUrl, looksLikeNostrBech32Identifier, looksLikeRelayUrlInput, normalizeAnyRelayUrl, normalizeHttpRelayUrl } from '@/lib/url'
import { normalizeToDTag } from '@/lib/search-parser'
import { cn } from '@/lib/utils'
import { useSmartNoteNavigation, useSmartHashtagNavigation } from '@/PageManager'
@ -56,7 +56,9 @@ const SearchBar = forwardRef< @@ -56,7 +56,9 @@ const SearchBar = forwardRef<
return undefined
}
const trimmed = input.trim()
if (!trimmed || looksLikeNostrBech32Identifier(trimmed)) return undefined
if (!trimmed || looksLikeNostrBech32Identifier(trimmed) || !looksLikeRelayUrlInput(trimmed)) {
return undefined
}
try {
const n = normalizeAnyRelayUrl(trimmed) || normalizeHttpRelayUrl(trimmed)
if (!n || (!isWebsocketUrl(n) && !isKind10243HttpRelayTagUrl(n))) return undefined

24
src/lib/url-relay-input.test.ts

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
import { describe, expect, it } from 'vitest'
import { looksLikeRelayUrlInput } from '@/lib/url'
describe('looksLikeRelayUrlInput', () => {
it('rejects profile names and partial username typing', () => {
for (const name of ['N', 'Nu', 'Nus', 'Nusa', 'alice', '@bob']) {
expect(looksLikeRelayUrlInput(name)).toBe(false)
}
})
it('accepts relay URL shapes', () => {
expect(looksLikeRelayUrlInput('wss://relay.example.com/')).toBe(true)
expect(looksLikeRelayUrlInput('ws://localhost:4869/')).toBe(true)
expect(looksLikeRelayUrlInput('https://index.example.com/')).toBe(true)
expect(looksLikeRelayUrlInput('relay.nostr1.com')).toBe(true)
expect(looksLikeRelayUrlInput('nostr.wine')).toBe(true)
})
it('rejects bech32 identifiers', () => {
expect(
looksLikeRelayUrlInput('npub1uq6dv4yq94704gk5r22jsqg9gy2wpxkk5dft9q5gugc8tj53nq2qg5q22d')
).toBe(false)
})
})

16
src/lib/url.ts

@ -41,6 +41,20 @@ export function looksLikeNostrBech32Identifier(value: string): boolean { @@ -41,6 +41,20 @@ export function looksLikeNostrBech32Identifier(value: string): boolean {
return /^(npub|nprofile|nevent|note|naddr)1[a-z0-9]+$/i.test(v)
}
/**
* True when free-text input plausibly targets a relay URL (scheme, `://`, or hostname shape).
* Usernames, hashtags, and partial profile names must not trigger relay normalization.
*/
export function looksLikeRelayUrlInput(value: string): boolean {
const v = value.trim()
if (!v || looksLikeNostrBech32Identifier(v)) return false
if (/^(wss?|https?):?\/?/i.test(v)) return true
if (v.includes('://')) return true
// hostname.tld — e.g. relay.example.com, nostr.wine (not bare names like "Nusa")
if (/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}(?:[:/].*)?$/i.test(v)) return true
return false
}
/** True when normalized to a WebSocket relay or kind-10243 HTTP index base. */
export function isValidRelayFetchUrl(url: string): boolean {
const trimmed = url.trim()
@ -235,7 +249,7 @@ export function normalizeUrl(url: string): string { @@ -235,7 +249,7 @@ export function normalizeUrl(url: string): string {
const trimmed = url.trim()
if (!trimmed) return ''
if (!trimmed.includes('://')) {
if (!looksLikeNostrBech32Identifier(trimmed)) {
if (!looksLikeNostrBech32Identifier(trimmed) && looksLikeRelayUrlInput(trimmed)) {
logger.warn('WebSocket relay URL requires ws: or wss: prefix', { url: trimmed })
}
return ''

Loading…
Cancel
Save