12 changed files with 186 additions and 43 deletions
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
import { describe, expect, it } from 'vitest' |
||||
import { |
||||
filterViewerBlockedRelaysForFetch, |
||||
parseBlockedRelayUrlsFromEvent, |
||||
setViewerBlockedRelayUrls |
||||
} from './viewer-blocked-relays' |
||||
|
||||
describe('viewer-blocked-relays', () => { |
||||
it('parseBlockedRelayUrlsFromEvent dedupes relay tags', () => { |
||||
setViewerBlockedRelayUrls([]) |
||||
const urls = parseBlockedRelayUrlsFromEvent({ |
||||
kind: 10006, |
||||
tags: [ |
||||
['relay', 'wss://freelay.sovbit.host/'], |
||||
['relay', 'wss://freelay.sovbit.host'] |
||||
], |
||||
content: '', |
||||
created_at: 1, |
||||
id: 'x', |
||||
pubkey: 'p', |
||||
sig: 's' |
||||
}) |
||||
expect(urls).toEqual(['wss://freelay.sovbit.host/']) |
||||
}) |
||||
|
||||
it('filterViewerBlockedRelaysForFetch matches hostname across schemes', () => { |
||||
setViewerBlockedRelayUrls(['wss://freelay.sovbit.host/']) |
||||
expect( |
||||
filterViewerBlockedRelaysForFetch([ |
||||
'wss://freelay.sovbit.host/', |
||||
'wss://relay.example.com/', |
||||
'https://freelay.sovbit.host/' |
||||
]) |
||||
).toEqual(['wss://relay.example.com/']) |
||||
}) |
||||
}) |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
import type { Event } from 'nostr-tools' |
||||
import { isRelayBlockedByUser } from '@/lib/relay-blocked' |
||||
import { normalizeAnyRelayUrl } from '@/lib/url' |
||||
|
||||
let viewerBlockedRelayUrls: readonly string[] = [] |
||||
|
||||
/** Kind 10006 `relay` tags → normalized URLs (deduped). */ |
||||
export function parseBlockedRelayUrlsFromEvent(event: Event | null | undefined): string[] { |
||||
const out: string[] = [] |
||||
if (!event) return out |
||||
event.tags.forEach(([tagName, tagValue]) => { |
||||
if (tagName !== 'relay' || !tagValue) return |
||||
const n = normalizeAnyRelayUrl(tagValue) |
||||
if (n && !out.includes(n)) out.push(n) |
||||
}) |
||||
return out |
||||
} |
||||
|
||||
/** Updated from IDB hydration and {@link FavoriteRelaysProvider} when the block list changes. */ |
||||
export function setViewerBlockedRelayUrls(urls: readonly string[]): void { |
||||
viewerBlockedRelayUrls = urls.length ? [...urls] : [] |
||||
} |
||||
|
||||
export function getViewerBlockedRelayUrls(): readonly string[] { |
||||
return viewerBlockedRelayUrls |
||||
} |
||||
|
||||
/** Drop user-blocked relays (hostname-aware) before any REQ / query / WebSocket connect. */ |
||||
export function filterViewerBlockedRelaysForFetch(urls: readonly string[]): string[] { |
||||
if (!viewerBlockedRelayUrls.length) return [...urls] |
||||
return urls.filter((u) => !isRelayBlockedByUser(u, viewerBlockedRelayUrls)) |
||||
} |
||||
Loading…
Reference in new issue