feat(graperank): add nostr.oxtr.dev and nos.lol to the content-aggregator set

Per-relay attribution on observer 460c25e6 showed two big general relays hold
kind:3 for a chunk of the missing authors that no profile indexer has:
nostr.oxtr.dev (76 distinct) and nos.lol (72). Add both to the aggregator set
so the patient kind:3-only recovery pass sweeps them alongside the indexers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSW59hJtP4Yn8fnRUxc7F5
This commit is contained in:
Claude
2026-07-08 17:02:18 +00:00
parent 7598a157dd
commit eef2832bf4
@@ -106,16 +106,20 @@ object GrapeRankCommand {
// Network-wide aggregators that scrape and hold kind:3 for users whose own
// outbox lacks it. The crawler queries these for a straggler's CONTENT (kind:3),
// not just their kind:10002 relay list. Measured on observer 460c25e6: querying
// user.kindpag.es for kind:3 alone recovers ~180 stragglers the pure outbox model
// never finds. The profile indexers (kindpag/purplepag/coracle/yabu/nostr1) plus
// the ActivityPub bridges (ditto/momostr/mostr, which host bridged users' lists).
// not just their kind:10002 relay list. Measured on observer 460c25e6, the distinct
// missing authors whose kind:3 each holds: kindpag.es 369, yabu 126, oxtr.dev 76,
// nos.lol 72, ditto 56, nostr1 29, momostr 11, mostr 3. So beyond the profile
// indexers (kindpag/purplepag/coracle/yabu/nostr1) and the ActivityPub bridges
// (ditto/momostr/mostr, which host bridged users' lists), two big general relays --
// nostr.oxtr.dev and nos.lol -- carry ~150 more that no indexer has.
private val CONTENT_AGGREGATOR_RELAYS: Set<NormalizedRelayUrl> =
DefaultIndexerRelayList +
listOf(
"wss://relay.ditto.pub",
"wss://relay.momostr.pink",
"wss://relay.mostr.pub",
"wss://nostr.oxtr.dev",
"wss://nos.lol",
).mapNotNull { RelayUrlNormalizer.normalizeOrNull(it) }.toSet()
suspend fun dispatch(