Browse Source

filter out other people's local relays. deduplicate relay list

imwald
Silberengel 5 months ago
parent
commit
6c282bd008
  1. 38
      src/components/PostEditor/PostContent.tsx
  2. 15
      src/components/PostEditor/PostRelaySelector.tsx
  3. 99
      src/services/relay-selection.service.ts

38
src/components/PostEditor/PostContent.tsx

@ -140,17 +140,11 @@ export default function PostContent({ @@ -140,17 +140,11 @@ export default function PostContent({
// Extract mentions from content for public messages
const extractMentionsFromContent = useCallback(async (content: string) => {
try {
// First try to extract nostr: protocol mentions
// Extract nostr: protocol mentions
const { pubkeys: nostrPubkeys } = await extractMentions(content, undefined)
// Also extract regular @ mentions (simple pattern for now)
const atMentions = content.match(/@[a-zA-Z0-9_]+/g) || []
console.log('Nostr mentions:', nostrPubkeys)
console.log('@ mentions:', atMentions)
// For now, we'll use the nostr mentions and show that we detected @ mentions
// In a real implementation, you'd resolve @ mentions to pubkeys
// For now, we'll use the nostr mentions
// In a real implementation, you'd also resolve @ mentions to pubkeys
setExtractedMentions(nostrPubkeys)
} catch (error) {
console.error('Error extracting mentions:', error)
@ -495,23 +489,15 @@ export default function PostContent({ @@ -495,23 +489,15 @@ export default function PostContent({
</div>
))}
{!isPoll && (
<>
{console.log('PostContent: Rendering PostRelaySelector with:', {
extractedMentions,
isPublicMessage,
isPoll,
textLength: text.length
})}
<PostRelaySelector
setIsProtectedEvent={setIsProtectedEvent}
setAdditionalRelayUrls={setAdditionalRelayUrls}
parentEvent={parentEvent}
openFrom={openFrom}
content={text}
isPublicMessage={isPublicMessage}
mentions={extractedMentions}
/>
</>
<PostRelaySelector
setIsProtectedEvent={setIsProtectedEvent}
setAdditionalRelayUrls={setAdditionalRelayUrls}
parentEvent={parentEvent}
openFrom={openFrom}
content={text}
isPublicMessage={isPublicMessage}
mentions={extractedMentions}
/>
)}
<div className="flex items-center justify-between">
<div className="flex gap-2 items-center">

15
src/components/PostEditor/PostRelaySelector.tsx

@ -122,24 +122,11 @@ export default function PostRelaySelector({ @@ -122,24 +122,11 @@ export default function PostRelaySelector({
// Separate effect for mention changes in non-discussion replies
useEffect(() => {
console.log('PostRelaySelector: Mentions effect triggered', {
mentions,
previousMentions,
isDiscussionReply,
mentionsLength: mentions.length,
previousMentionsLength: previousMentions.length
})
if (isDiscussionReply) {
console.log('PostRelaySelector: Skipping mention update - is discussion reply')
return // Skip for discussion replies
}
if (isDiscussionReply) return // Skip for discussion replies
const mentionsChanged = JSON.stringify(mentions) !== JSON.stringify(previousMentions)
console.log('PostRelaySelector: Mentions changed?', mentionsChanged)
if (mentionsChanged) {
console.log('PostRelaySelector: Updating relay selection due to mention changes')
setPreviousMentions(mentions)
// Update relay selection when mentions change

99
src/services/relay-selection.service.ts

@ -2,7 +2,7 @@ import { Event, kinds } from 'nostr-tools' @@ -2,7 +2,7 @@ import { Event, kinds } from 'nostr-tools'
import { ExtendedKind } from '@/constants'
import { FAST_WRITE_RELAY_URLS } from '@/constants'
import client from '@/services/client.service'
import { normalizeUrl } from '@/lib/url'
import { normalizeUrl, isLocalNetworkUrl } from '@/lib/url'
import { TRelaySet } from '@/types'
export interface RelaySelectionContext {
@ -28,6 +28,20 @@ export interface RelaySelectionResult { @@ -28,6 +28,20 @@ export interface RelaySelectionResult {
}
class RelaySelectionService {
/**
* Filter out local network relays from other users' relay lists
* We should only use our own local relays, not other users' local relays
*/
private filterLocalRelaysFromOthers(relays: string[], isOwnRelays: boolean = false): string[] {
if (isOwnRelays) {
// For our own relays, keep all of them including local ones
return relays
}
// For other users' relays, filter out local network relays
return relays.filter(relay => !isLocalNetworkUrl(relay))
}
/**
* Main entry point for relay selection logic
*/
@ -65,31 +79,45 @@ class RelaySelectionService { @@ -65,31 +79,45 @@ class RelaySelectionService {
const selectableRelays = new Set<string>()
// Helper function to safely add normalized URLs
const addRelay = (url: string) => {
if (!url) return
const normalized = normalizeUrl(url)
if (normalized) {
selectableRelays.add(normalized)
} else {
// If normalization fails, add the original URL but log a warning
console.warn('Failed to normalize relay URL:', url)
selectableRelays.add(url)
}
}
// Always include user's write relays (or fallback to fast write relays)
const userRelays = userWriteRelays.length > 0 ? userWriteRelays : FAST_WRITE_RELAY_URLS
userRelays.forEach(url => selectableRelays.add(normalizeUrl(url) || url))
userRelays.forEach(addRelay)
// Always include favorite relays
favoriteRelays.forEach(url => selectableRelays.add(normalizeUrl(url) || url))
favoriteRelays.forEach(addRelay)
// Always include relays from relay sets
relaySets.forEach(set => {
set.relayUrls.forEach(url => selectableRelays.add(normalizeUrl(url) || url))
set.relayUrls.forEach(addRelay)
})
// Add contextual relays for replies and public messages
if (parentEvent || isPublicMessage) {
const contextualRelays = await this.getContextualRelays(context)
contextualRelays.forEach(url => selectableRelays.add(normalizeUrl(url) || url))
contextualRelays.forEach(addRelay)
}
// If called with specific relay URLs (e.g., from openFrom), include those
if (openFrom && openFrom.length > 0) {
openFrom.forEach(url => selectableRelays.add(normalizeUrl(url) || url))
openFrom.forEach(addRelay)
}
// Filter out blocked relays
return this.filterBlockedRelays(Array.from(selectableRelays).filter(Boolean), context.blockedRelays)
// Filter out blocked relays and return deduplicated list
const deduplicatedRelays = Array.from(selectableRelays).filter(Boolean)
return this.filterBlockedRelays(deduplicatedRelays, context.blockedRelays)
}
/**
@ -103,11 +131,12 @@ class RelaySelectionService { @@ -103,11 +131,12 @@ class RelaySelectionService {
try {
// For replies (any kind) and public messages
if (parentEvent || isPublicMessage) {
// Get the replied-to author's read relays
// Get the replied-to author's read relays (filter out their local relays)
if (parentEvent) {
const authorRelayList = await client.fetchRelayList(parentEvent.pubkey)
if (authorRelayList?.read) {
authorRelayList.read.slice(0, 4).forEach(url => contextualRelays.add(url))
const filteredRelays = this.filterLocalRelaysFromOthers(authorRelayList.read)
filteredRelays.slice(0, 4).forEach(url => contextualRelays.add(url))
}
}
@ -142,7 +171,9 @@ class RelaySelectionService { @@ -142,7 +171,9 @@ class RelaySelectionService {
const relayList = await client.fetchRelayList(pubkey)
// Use write relays for replies, read relays for public messages
const relayType = isPublicMessage ? 'read' : 'write'
return relayList?.[relayType] || []
const userRelays = relayList?.[relayType] || []
// Filter out local relays from other users
return this.filterLocalRelaysFromOthers(userRelays)
} catch (error) {
console.warn(`Failed to fetch relay list for ${pubkey}:`, error)
return []
@ -181,6 +212,8 @@ class RelaySelectionService { @@ -181,6 +212,8 @@ class RelaySelectionService {
// If called with specific relay URLs, use those
if (openFrom && openFrom.length > 0) {
selectedRelays = openFrom.map(url => normalizeUrl(url) || url).filter(Boolean)
// Deduplicate the selected relays
selectedRelays = Array.from(new Set(selectedRelays))
}
// For discussion replies, use relay hint from the kind 11 at the top of the thread
else if (parentEvent && (parentEvent.kind === ExtendedKind.DISCUSSION || parentEvent.kind === ExtendedKind.COMMENT)) {
@ -198,6 +231,8 @@ class RelaySelectionService { @@ -198,6 +231,8 @@ class RelaySelectionService {
// Get user's write relays
const userRelays = userWriteRelays.length > 0 ? userWriteRelays : FAST_WRITE_RELAY_URLS
selectedRelays = userRelays.map(url => normalizeUrl(url) || url).filter(Boolean)
// Deduplicate the selected relays
selectedRelays = Array.from(new Set(selectedRelays))
// Add mention relays
if (userPubkey) {
@ -221,7 +256,9 @@ class RelaySelectionService { @@ -221,7 +256,9 @@ class RelaySelectionService {
mentionedPubkeys.map(async (pubkey) => {
try {
const relayList = await client.fetchRelayList(pubkey)
return relayList?.write || []
const userRelays = relayList?.write || []
// Filter out local relays from other users
return this.filterLocalRelaysFromOthers(userRelays)
} catch (error) {
console.warn(`Failed to fetch relay list for ${pubkey}:`, error)
return []
@ -230,6 +267,8 @@ class RelaySelectionService { @@ -230,6 +267,8 @@ class RelaySelectionService {
)
const mentionRelays = mentionRelayLists.flat().map(url => normalizeUrl(url) || url).filter(Boolean)
selectedRelays = [...selectedRelays, ...mentionRelays]
// Deduplicate after adding mention relays
selectedRelays = Array.from(new Set(selectedRelays))
}
}
}
@ -237,6 +276,8 @@ class RelaySelectionService { @@ -237,6 +276,8 @@ class RelaySelectionService {
else {
const defaultRelays = userWriteRelays.length > 0 ? userWriteRelays : FAST_WRITE_RELAY_URLS
selectedRelays = defaultRelays.map(url => normalizeUrl(url) || url).filter(Boolean)
// Deduplicate the selected relays
selectedRelays = Array.from(new Set(selectedRelays))
}
// Filter out blocked relays
@ -253,7 +294,14 @@ class RelaySelectionService { @@ -253,7 +294,14 @@ class RelaySelectionService {
try {
// Add sender's write relays (outboxes) - fallback to fast write relays if no user relays
const senderRelays = userWriteRelays.length > 0 ? userWriteRelays : FAST_WRITE_RELAY_URLS
senderRelays.forEach(url => relays.add(normalizeUrl(url) || url))
senderRelays.forEach(url => {
const normalized = normalizeUrl(url)
if (normalized) {
relays.add(normalized)
} else {
relays.add(url)
}
})
// Add receiver's read relays (inboxes)
if (isPublicMessage && content && userPubkey) {
@ -266,21 +314,38 @@ class RelaySelectionService { @@ -266,21 +314,38 @@ class RelaySelectionService {
mentionedPubkeys.map(async (pubkey) => {
try {
const relayList = await client.fetchRelayList(pubkey)
return relayList?.read || []
const userRelays = relayList?.read || []
// Filter out local relays from other users
return this.filterLocalRelaysFromOthers(userRelays)
} catch (error) {
console.warn(`Failed to fetch relay list for ${pubkey}:`, error)
return []
}
})
)
receiverRelayLists.flat().forEach(url => relays.add(normalizeUrl(url) || url))
receiverRelayLists.flat().forEach(url => {
const normalized = normalizeUrl(url)
if (normalized) {
relays.add(normalized)
} else {
relays.add(url)
}
})
}
} else if (parentEvent && parentEvent.kind === ExtendedKind.PUBLIC_MESSAGE) {
// For public message replies, get original sender's read relays
// For public message replies, get original sender's read relays (filter out their local relays)
try {
const senderRelayList = await client.fetchRelayList(parentEvent.pubkey)
if (senderRelayList?.read) {
senderRelayList.read.forEach(url => relays.add(normalizeUrl(url) || url))
const filteredRelays = this.filterLocalRelaysFromOthers(senderRelayList.read)
filteredRelays.forEach(url => {
const normalized = normalizeUrl(url)
if (normalized) {
relays.add(normalized)
} else {
relays.add(url)
}
})
}
} catch (error) {
console.warn(`Failed to fetch relay list for ${parentEvent.pubkey}:`, error)

Loading…
Cancel
Save