5 changed files with 92 additions and 19 deletions
@ -0,0 +1,34 @@ |
|||||||
|
import { kinds } from 'nostr-tools' |
||||||
|
import { ExtendedKind } from '@/constants' |
||||||
|
import { |
||||||
|
filterPublishingRelayUrls, |
||||||
|
filterRelayUrlsForSocialKindPublish, |
||||||
|
isSocialKindBlockedRelayUrl |
||||||
|
} from '@/lib/social-kind-blocked-relays' |
||||||
|
import { describe, expect, it } from 'vitest' |
||||||
|
|
||||||
|
describe('social-kind-blocked-relays', () => { |
||||||
|
it('matches essayist by hostname even with a path suffix', () => { |
||||||
|
expect(isSocialKindBlockedRelayUrl('wss://essayist.decentnewsroom.com/')).toBe(true) |
||||||
|
expect(isSocialKindBlockedRelayUrl('wss://essayist.decentnewsroom.com/npub1abc')).toBe(true) |
||||||
|
}) |
||||||
|
|
||||||
|
it('strips essayist for kind 1 and reactions but not long-form', () => { |
||||||
|
const urls = ['wss://relay.damus.io/', 'wss://essayist.decentnewsroom.com/'] |
||||||
|
expect(filterRelayUrlsForSocialKindPublish(urls, kinds.ShortTextNote)).toEqual([ |
||||||
|
'wss://relay.damus.io/' |
||||||
|
]) |
||||||
|
expect(filterRelayUrlsForSocialKindPublish(urls, kinds.Reaction)).toEqual([ |
||||||
|
'wss://relay.damus.io/' |
||||||
|
]) |
||||||
|
expect(filterRelayUrlsForSocialKindPublish(urls, kinds.LongFormArticle)).toEqual(urls) |
||||||
|
}) |
||||||
|
|
||||||
|
it('filterPublishingRelayUrls applies read-only and social filters', () => { |
||||||
|
const out = filterPublishingRelayUrls( |
||||||
|
['wss://nostr.land/', 'wss://essayist.decentnewsroom.com/', 'wss://relay.damus.io/'], |
||||||
|
ExtendedKind.COMMENT |
||||||
|
) |
||||||
|
expect(out).toEqual(['wss://relay.damus.io/']) |
||||||
|
}) |
||||||
|
}) |
||||||
@ -0,0 +1,47 @@ |
|||||||
|
import { SOCIAL_KIND_BLOCKED_RELAY_URLS, isSocialKindBlockedKind } from '@/constants' |
||||||
|
import { filterRelaysForEventPublish } from '@/lib/relay-publish-filter' |
||||||
|
import { dedupeNormalizeRelayUrlsOrdered } from '@/lib/relay-url-priority' |
||||||
|
import { normalizeRelayUrlByScheme } from '@/lib/url' |
||||||
|
|
||||||
|
function relayHostname(url: string): string | null { |
||||||
|
const normalized = normalizeRelayUrlByScheme(url) || url.trim() |
||||||
|
if (!normalized) return null |
||||||
|
try { |
||||||
|
return new URL(normalized).hostname.toLowerCase() |
||||||
|
} catch { |
||||||
|
return null |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const blockedExactKeys = new Set( |
||||||
|
SOCIAL_KIND_BLOCKED_RELAY_URLS.map((u) => (normalizeRelayUrlByScheme(u) || u).toLowerCase()).filter(Boolean) |
||||||
|
) |
||||||
|
|
||||||
|
const blockedHostnames = new Set( |
||||||
|
SOCIAL_KIND_BLOCKED_RELAY_URLS.map((u) => relayHostname(u)).filter((h): h is string => !!h) |
||||||
|
) |
||||||
|
|
||||||
|
/** True when `url` is (or is hosted on) a relay in {@link SOCIAL_KIND_BLOCKED_RELAY_URLS}. */ |
||||||
|
export function isSocialKindBlockedRelayUrl(url: string): boolean { |
||||||
|
const key = (normalizeRelayUrlByScheme(url) || url.trim()).toLowerCase() |
||||||
|
if (!key) return false |
||||||
|
if (blockedExactKeys.has(key)) return true |
||||||
|
const host = relayHostname(url) |
||||||
|
return host != null && blockedHostnames.has(host) |
||||||
|
} |
||||||
|
|
||||||
|
/** Strip social-kind-blocked relays for kinds in {@link isSocialKindBlockedKind}. */ |
||||||
|
export function filterRelayUrlsForSocialKindPublish( |
||||||
|
urls: readonly string[], |
||||||
|
eventKind: number |
||||||
|
): string[] { |
||||||
|
if (!isSocialKindBlockedKind(eventKind)) return [...urls] |
||||||
|
return urls.filter((url) => !isSocialKindBlockedRelayUrl(url)) |
||||||
|
} |
||||||
|
|
||||||
|
/** Read-only / profile-index filter + social-kind-blocked strip + dedupe (publish stack). */ |
||||||
|
export function filterPublishingRelayUrls(urls: readonly string[], eventKind: number): string[] { |
||||||
|
return dedupeNormalizeRelayUrlsOrdered( |
||||||
|
filterRelayUrlsForSocialKindPublish(filterRelaysForEventPublish(urls, eventKind), eventKind) |
||||||
|
) |
||||||
|
} |
||||||
Loading…
Reference in new issue