diff --git a/src/components/Embedded/EmbeddedNote.tsx b/src/components/Embedded/EmbeddedNote.tsx index 215a4f95..5c5cc034 100644 --- a/src/components/Embedded/EmbeddedNote.tsx +++ b/src/components/Embedded/EmbeddedNote.tsx @@ -5,7 +5,10 @@ import { getFavoritesFeedRelayUrls } from '@/lib/favorites-feed-relays' import { LIVE_ACTIVITY_KINDS } from '@/lib/live-activities' import { isCalendarEventKind } from '@/lib/calendar-event' import { isRenderableNoteKind } from '@/lib/note-renderable-kinds' -import { shouldDropEventOnIngest } from '@/lib/event-ingest-filter' +import { + shouldDropEventOnIngest, + type ShouldDropEventOnIngestOptions +} from '@/lib/event-ingest-filter' import { normalizeUrl } from '@/lib/url' import { cn } from '@/lib/utils' import client, { eventService } from '@/services/client.service' @@ -19,7 +22,11 @@ import { syncViewerRelayStackNostrLandAggrEligible, urlsForViewerNostrLandAggrEligibilitySync } from '@/lib/nostr-land-relay-eligibility' -import { sanitizeRelayUrlsForFetch } from '@/lib/read-only-relay-personal' +import { + enterMetadataRelaysOnlyBypass, + leaveMetadataRelaysOnlyBypass, + sanitizeRelayUrlsForFetch +} from '@/lib/read-only-relay-personal' import { useFavoriteRelays } from '@/providers/favorite-relays-context' import { useIsEventDeleted } from '@/providers/DeletedEventProvider' import { useReply } from '@/providers/ReplyProvider' @@ -73,6 +80,12 @@ function coordinateFromNoteId(noteId: string): string | null { } } +/** Match {@link EventService.fetchEvent} / wide-relay ingest: explicit id lookup relaxes kind-1 spam filters. */ +function embedIngestOptsForNoteKey(noteKey: string): ShouldDropEventOnIngestOptions | undefined { + const hex = hexEventIdFromNoteId(noteKey) + return hex ? { explicitNoteLookupHexId: hex } : undefined +} + /** True if `fetchEventWithExternalRelays(noteId, …)` can build a REQ filter (hex, note, nevent, naddr). */ function canSearchOnExternalRelays(noteId: string): boolean { if (hexEventIdFromNoteId(noteId)) return true @@ -221,6 +234,8 @@ function EmbeddedNoteFetched({ const [isFetching, setIsFetching] = useState(true) const eventRef = useRef(undefined) const retryIntervalRef = useRef | null>(null) + const embedNoteKeyRef = useRef(noteId.trim()) + embedNoteKeyRef.current = noteId.trim() eventRef.current = event const relayHintsFromParent = useMemo( @@ -259,12 +274,13 @@ function EmbeddedNoteFetched({ const resolveAndSet = useCallback( (ev: Event | undefined) => { - if (!ev || isEventDeleted(ev) || shouldDropEventOnIngest(ev)) return false + const ingestOpts = embedIngestOptsForNoteKey(embedNoteKeyRef.current) + if (!ev || isEventDeleted(ev) || shouldDropEventOnIngest(ev, ingestOpts)) return false if (retryIntervalRef.current) { clearInterval(retryIntervalRef.current) retryIntervalRef.current = null } - client.addEventToCache(ev) + client.addEventToCache(ev, ingestOpts) setEvent(ev) addReplies([ev]) return true @@ -289,12 +305,15 @@ function EmbeddedNoteFetched({ containingEventRef.current = containingEvent useEffect(() => { + enterMetadataRelaysOnlyBypass() let cancelled = false const noteKey = noteId.trim() + embedNoteKeyRef.current = noteKey eventRef.current = undefined setEvent(undefined) setIsFetching(true) + const ingestOpts = embedIngestOptsForNoteKey(noteKey) const resolve = (ev: Event | undefined) => resolveAndSetRef.current(ev) const tryShortcuts = (): boolean => { @@ -315,7 +334,7 @@ function EmbeddedNoteFetched({ const { fetchRelayOpts: opts, wideRelaysStatic: wideUrls } = embedFetchCtxRef.current const hex = hexEventIdFromNoteId(noteKey) const isUsable = (e: Event) => - !isEventDeletedRef.current(e) && !shouldDropEventOnIngest(e) + !isEventDeletedRef.current(e) && !shouldDropEventOnIngest(e, ingestOpts) try { const chosen = await firstResolvedUsableEmbedEvent( [ @@ -367,6 +386,7 @@ function EmbeddedNoteFetched({ if (eventRef.current) { return () => { cancelled = true + leaveMetadataRelaysOnlyBypass() if (retryIntervalRef.current) { clearInterval(retryIntervalRef.current) retryIntervalRef.current = null @@ -386,6 +406,7 @@ function EmbeddedNoteFetched({ return () => { cancelled = true + leaveMetadataRelaysOnlyBypass() if (retryIntervalRef.current) { clearInterval(retryIntervalRef.current) retryIntervalRef.current = null diff --git a/src/constants.ts b/src/constants.ts index 1c310cb1..77653d97 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -462,7 +462,9 @@ export const READ_ONLY_RELAY_URLS = [ 'wss://search.nos.today', 'wss://relay.nip46.com', 'wss://filter.nostr.wine', - 'wss://primus.nostr1.com' + 'wss://primus.nostr1.com', + 'wss://feeds.nostrarchives.com', + 'wss://feeds.nostrarchives.com/notes/trending/reactions/today' ] /** diff --git a/src/services/client-events.service.ts b/src/services/client-events.service.ts index 6c9805d2..36626889 100644 --- a/src/services/client-events.service.ts +++ b/src/services/client-events.service.ts @@ -513,7 +513,7 @@ export class EventService { } const hexIds = [...hexSet].filter((id) => { - if (this.getSessionEventIfAllowed(id)) return false + if (this.getSessionEventIfAllowed(id, true)) return false if (this.embeddedPrefetchHexScheduled.has(id)) return false this.embeddedPrefetchHexScheduled.add(id) return true @@ -558,14 +558,17 @@ export class EventService { .filter((id) => /^[0-9a-f]{64}$/.test(id)) ) ] - let toFetch = hexIds.filter((id) => !this.getSessionEventIfAllowed(id)) + let toFetch = hexIds.filter((id) => !this.getSessionEventIfAllowed(id, true)) if (toFetch.length === 0) return const archived = await prefetchArchivedEvents(toFetch) for (const ev of archived) { - if (!shouldDropEventOnIngest(ev)) this.addEventToCache(ev) + const hex = ev.id?.toLowerCase() + const ingestOpts = + hex && /^[0-9a-f]{64}$/.test(hex) ? { explicitNoteLookupHexId: hex } : undefined + this.addEventToCache(ev, ingestOpts) } - toFetch = toFetch.filter((id) => !this.getSessionEventIfAllowed(id)) + toFetch = toFetch.filter((id) => !this.getSessionEventIfAllowed(id, true)) if (toFetch.length === 0) return const hints = (opts?.relayHints ?? []) @@ -590,7 +593,10 @@ export class EventService { } ) for (const ev of events) { - this.addEventToCache(ev) + const hex = ev.id?.toLowerCase() + const ingestOpts = + hex && /^[0-9a-f]{64}$/.test(hex) ? { explicitNoteLookupHexId: hex } : undefined + this.addEventToCache(ev, ingestOpts) } } }