refactor: use applesauce helpers for relay operations in chat adapters

- Use mergeRelaySets for relay deduplication and normalization
- Use getOutboxes helper instead of manual relay list parsing
- Simplify getThreadRelays in NIP-10 adapter
- Simplify loadReplyMessage in NIP-10, NIP-29, and NIP-53 adapters
This commit is contained in:
Claude
2026-01-22 15:39:25 +00:00
parent 259f4b55c9
commit 9e716d813b
3 changed files with 32 additions and 69 deletions

View File

@@ -22,7 +22,8 @@ import pool from "@/services/relay-pool";
import { publishEventToRelays } from "@/services/hub";
import accountManager from "@/services/accounts";
import { AGGREGATOR_RELAYS } from "@/services/loaders";
import { normalizeURL } from "applesauce-core/helpers";
import { mergeRelaySets } from "applesauce-core/helpers";
import { getOutboxes } from "applesauce-core/helpers/mailboxes";
import { getEventPointerFromETag } from "applesauce-core/helpers/pointers";
import { EventFactory } from "applesauce-core/event-factory";
import {
@@ -516,16 +517,9 @@ export class Nip10Adapter extends ChatProtocolAdapter {
return cachedEvent;
}
// Build relay list: conversation relays + pointer relay hints (deduplicated)
// Build relay list: conversation relays + pointer relay hints (deduplicated and normalized)
const conversationRelays = conversation.metadata?.relays || [];
const relays = [...conversationRelays];
if (pointer.relays) {
for (const relay of pointer.relays) {
if (!relays.includes(relay)) {
relays.push(relay);
}
}
}
const relays = mergeRelaySets(conversationRelays, pointer.relays || []);
if (relays.length === 0) {
console.warn("[NIP-10] No relays for loading reply message");
@@ -635,52 +629,38 @@ export class Nip10Adapter extends ChatProtocolAdapter {
providedEvent: NostrEvent,
providedRelays: string[],
): Promise<string[]> {
const relays = new Set<string>();
const relaySets: string[][] = [];
// 1. Provided relay hints
providedRelays.forEach((r) => relays.add(normalizeURL(r)));
// 1. Provided relay hints (highest priority)
relaySets.push(providedRelays);
// 2. Root author's outbox relays (NIP-65) - highest priority
// 2. Root author's outbox relays (NIP-65)
try {
const rootOutbox = await this.getOutboxRelays(rootEvent.pubkey);
rootOutbox.slice(0, 3).forEach((r) => relays.add(normalizeURL(r)));
relaySets.push(rootOutbox.slice(0, 3));
} catch (err) {
console.warn("[NIP-10] Failed to get root author outbox:", err);
}
// 3. Collect unique participant pubkeys from both events' p-tags
const participantPubkeys = new Set<string>();
// Add p-tags from root event
for (const tag of rootEvent.tags) {
if (tag[0] === "p" && tag[1]) {
participantPubkeys.add(tag[1]);
}
if (tag[0] === "p" && tag[1]) participantPubkeys.add(tag[1]);
}
// Add p-tags from provided event
for (const tag of providedEvent.tags) {
if (tag[0] === "p" && tag[1]) {
participantPubkeys.add(tag[1]);
}
if (tag[0] === "p" && tag[1]) participantPubkeys.add(tag[1]);
}
// Add provided event author if different from root
if (providedEvent.pubkey !== rootEvent.pubkey) {
participantPubkeys.add(providedEvent.pubkey);
}
// 4. Fetch outbox relays from participant subset (limit to avoid slowdown)
// Take first 5 participants to get relay diversity without excessive fetching
const participantsToCheck = Array.from(participantPubkeys).slice(0, 5);
for (const pubkey of participantsToCheck) {
try {
const outbox = await this.getOutboxRelays(pubkey);
// Add 1 relay from each participant for diversity
if (outbox.length > 0) {
relays.add(normalizeURL(outbox[0]));
}
} catch (_err) {
if (outbox.length > 0) relaySets.push([outbox[0]]);
} catch {
// Silently continue if participant has no relay list
}
}
@@ -690,19 +670,22 @@ export class Nip10Adapter extends ChatProtocolAdapter {
if (activePubkey && !participantPubkeys.has(activePubkey)) {
try {
const userOutbox = await this.getOutboxRelays(activePubkey);
userOutbox.slice(0, 2).forEach((r) => relays.add(normalizeURL(r)));
relaySets.push(userOutbox.slice(0, 2));
} catch (err) {
console.warn("[NIP-10] Failed to get user outbox:", err);
}
}
// Merge all relay sets (handles deduplication and normalization)
let relays = mergeRelaySets(...relaySets);
// 6. Fallback to aggregator relays if we have too few
if (relays.size < 3) {
AGGREGATOR_RELAYS.forEach((r) => relays.add(r));
if (relays.length < 3) {
relays = mergeRelaySets(relays, AGGREGATOR_RELAYS);
}
// Limit to 10 relays max for performance
return Array.from(relays).slice(0, 10);
return relays.slice(0, 10);
}
/**
@@ -716,15 +699,8 @@ export class Nip10Adapter extends ChatProtocolAdapter {
if (!relayList) return [];
// Extract write relays (r tags with "write" or no marker)
return relayList.tags
.filter((t) => {
if (t[0] !== "r") return false;
const marker = t[2];
return !marker || marker === "write";
})
.map((t) => normalizeURL(t[1]))
.slice(0, 5); // Limit to 5
// Use applesauce helper to extract write relays
return getOutboxes(relayList).slice(0, 5);
}
/**

View File

@@ -21,6 +21,7 @@ import { publishEventToRelays, publishEvent } from "@/services/hub";
import accountManager from "@/services/accounts";
import { getTagValues, getQuotePointer } from "@/lib/nostr-utils";
import { getEventPointerFromETag } from "applesauce-core/helpers/pointers";
import { mergeRelaySets } from "applesauce-core/helpers";
import { normalizeRelayURL } from "@/lib/relay-url";
import { EventFactory } from "applesauce-core/event-factory";
import {
@@ -803,20 +804,12 @@ export class Nip29Adapter extends ChatProtocolAdapter {
return cachedEvent;
}
// Build relay list: group relay + pointer relay hints (deduplicated)
const relays: string[] = [];
// Build relay list: group relay + pointer relay hints (deduplicated and normalized)
const groupRelayUrl = conversation.metadata?.relayUrl;
if (groupRelayUrl) {
relays.push(groupRelayUrl);
}
// Add relay hints from the pointer (q-tag relay hint)
if (pointer.relays) {
for (const relay of pointer.relays) {
if (!relays.includes(relay)) {
relays.push(relay);
}
}
}
const relays = mergeRelaySets(
groupRelayUrl ? [groupRelayUrl] : [],
pointer.relays || [],
);
if (relays.length === 0) {
console.warn("[NIP-29] No relays available for loading reply message");

View File

@@ -24,6 +24,7 @@ import { publishEventToRelays } from "@/services/hub";
import accountManager from "@/services/accounts";
import { AGGREGATOR_RELAYS } from "@/services/loaders";
import { getEventPointerFromETag } from "applesauce-core/helpers/pointers";
import { mergeRelaySets } from "applesauce-core/helpers";
import {
parseLiveActivity,
getLiveStatus,
@@ -666,20 +667,13 @@ export class Nip53Adapter extends ChatProtocolAdapter {
// Get conversation relays
const conversationRelays =
liveActivity?.relays && liveActivity.relays.length > 0
? [...liveActivity.relays]
? liveActivity.relays
: conversation.metadata?.relayUrl
? [conversation.metadata.relayUrl]
: [];
// Add pointer relay hints (deduplicated)
const relays = [...conversationRelays];
if (pointer.relays) {
for (const relay of pointer.relays) {
if (!relays.includes(relay)) {
relays.push(relay);
}
}
}
// Merge conversation relays with pointer relay hints (deduplicated and normalized)
const relays = mergeRelaySets(conversationRelays, pointer.relays || []);
if (relays.length === 0) {
console.warn("[NIP-53] No relays for loading reply message");