You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.2 KiB
94 lines
2.2 KiB
/** |
|
* Relay list fetcher (kind 10002 and 10432) |
|
*/ |
|
|
|
import { nostrClient } from '../nostr/nostr-client.js'; |
|
import { config } from '../nostr/config.js'; |
|
import type { NostrEvent } from '../../types/nostr.js'; |
|
|
|
export interface RelayInfo { |
|
url: string; |
|
read: boolean; |
|
write: boolean; |
|
} |
|
|
|
/** |
|
* Parse relay list from event |
|
*/ |
|
export function parseRelayList(event: NostrEvent): RelayInfo[] { |
|
const relays: RelayInfo[] = []; |
|
|
|
for (const tag of event.tags) { |
|
if (tag[0] === 'r' && tag[1]) { |
|
const url = tag[1]; |
|
const markers = tag.slice(2); |
|
|
|
// If no markers, relay is both read and write |
|
if (markers.length === 0) { |
|
relays.push({ url, read: true, write: true }); |
|
continue; |
|
} |
|
|
|
// Check for explicit markers |
|
const hasRead = markers.includes('read'); |
|
const hasWrite = markers.includes('write'); |
|
|
|
// If only 'read' marker: read=true, write=false |
|
// If only 'write' marker: read=false, write=true |
|
// If both or neither explicitly: both true (default behavior) |
|
const read = hasRead || (!hasRead && !hasWrite); |
|
const write = hasWrite || (!hasRead && !hasWrite); |
|
|
|
relays.push({ url, read, write }); |
|
} |
|
} |
|
|
|
return relays; |
|
} |
|
|
|
/** |
|
* Fetch relay lists for a pubkey (kind 10002 and 10432) |
|
*/ |
|
export async function fetchRelayLists( |
|
pubkey: string, |
|
relays?: string[] |
|
): Promise<{ |
|
inbox: string[]; |
|
outbox: string[]; |
|
}> { |
|
const relayList = relays || [ |
|
...config.defaultRelays, |
|
...config.profileRelays |
|
]; |
|
|
|
// Fetch both kind 10002 and 10432 |
|
const events = await nostrClient.fetchEvents( |
|
[ |
|
{ kinds: [10002], authors: [pubkey], limit: 1 }, |
|
{ kinds: [10432], authors: [pubkey], limit: 1 } |
|
], |
|
relayList, |
|
{ useCache: true, cacheResults: true } |
|
); |
|
|
|
const inbox: string[] = []; |
|
const outbox: string[] = []; |
|
|
|
for (const event of events) { |
|
const relayInfos = parseRelayList(event); |
|
for (const info of relayInfos) { |
|
if (info.read && !inbox.includes(info.url)) { |
|
inbox.push(info.url); |
|
} |
|
if (info.write && !outbox.includes(info.url)) { |
|
outbox.push(info.url); |
|
} |
|
} |
|
} |
|
|
|
// Deduplicate |
|
return { |
|
inbox: [...new Set(inbox)], |
|
outbox: [...new Set(outbox)] |
|
}; |
|
}
|
|
|