84 lines
2.6 KiB
TypeScript
84 lines
2.6 KiB
TypeScript
import type { RelayMetadata } from '@/contexts/AppContext';
|
|
|
|
/** Relay used for NIP-50 search, trending, and streaming queries. */
|
|
export const DITTO_RELAY = 'wss://relay.ditto.pub/';
|
|
|
|
/** All Ditto relays used for search, trending, and streaming queries. */
|
|
export const DITTO_RELAYS: string[] = [
|
|
'wss://relay.ditto.pub/',
|
|
'wss://relay.dreamith.to/',
|
|
];
|
|
|
|
/** Relay used for kind 34236 addressable short video events, used by divine */
|
|
export const DIVINE_RELAY = 'wss://divine.video/';
|
|
|
|
/** Relay used for Zapstore app metadata (kind 32267) and releases (kind 30063). */
|
|
export const ZAPSTORE_RELAY = 'wss://relay.zapstore.dev';
|
|
|
|
/** Normalize a relay URL for deduplication (lowercase, strip trailing slash). */
|
|
function normalizeUrl(url: string): string {
|
|
return url.toLowerCase().replace(/\/+$/, '');
|
|
}
|
|
|
|
/**
|
|
* App default relays that are used as a fallback when the user has no NIP-65 relay list,
|
|
* and can be optionally combined with user relays.
|
|
*/
|
|
export const APP_RELAYS: RelayMetadata = {
|
|
relays: [
|
|
{ url: 'wss://relay.ditto.pub/', read: true, write: true },
|
|
{ url: 'wss://relay.dreamith.to/', read: true, write: true },
|
|
{ url: 'wss://relay.primal.net/', read: true, write: true },
|
|
{ url: 'wss://relay.damus.io/', read: true, write: true },
|
|
{ url: 'wss://nos.lol/', read: true, write: false },
|
|
],
|
|
updatedAt: 0,
|
|
};
|
|
|
|
/**
|
|
* Get the effective relay list based on user settings.
|
|
* Combines app relays with user relays if useAppRelays is true,
|
|
* otherwise returns only user relays.
|
|
*/
|
|
export function getEffectiveRelays(
|
|
userRelays: RelayMetadata,
|
|
useAppRelays: boolean
|
|
): RelayMetadata {
|
|
if (!useAppRelays) {
|
|
return deduplicateRelays(userRelays);
|
|
}
|
|
|
|
// Merge app relays with user relays, avoiding duplicates by normalized URL
|
|
const seen = new Set<string>();
|
|
const mergedRelays: RelayMetadata['relays'][number][] = [];
|
|
|
|
for (const relay of [...APP_RELAYS.relays, ...userRelays.relays]) {
|
|
const normalized = normalizeUrl(relay.url);
|
|
if (!seen.has(normalized)) {
|
|
seen.add(normalized);
|
|
mergedRelays.push(relay);
|
|
}
|
|
}
|
|
|
|
return {
|
|
relays: mergedRelays,
|
|
updatedAt: userRelays.updatedAt,
|
|
};
|
|
}
|
|
|
|
/** Deduplicate relays within a single list by normalized URL. */
|
|
function deduplicateRelays(metadata: RelayMetadata): RelayMetadata {
|
|
const seen = new Set<string>();
|
|
const relays: RelayMetadata['relays'][number][] = [];
|
|
|
|
for (const relay of metadata.relays) {
|
|
const normalized = normalizeUrl(relay.url);
|
|
if (!seen.has(normalized)) {
|
|
seen.add(normalized);
|
|
relays.push(relay);
|
|
}
|
|
}
|
|
|
|
return { relays, updatedAt: metadata.updatedAt };
|
|
}
|