clone of repo on github
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.
 
 
 
 

143 lines
3.5 KiB

import { activeInboxRelays, activeOutboxRelays } from "$lib/ndk";
import NDK from "@nostr-dev-kit/ndk";
import { TIMEOUTS } from "./search_constants";
import { get } from "svelte/store";
export interface RelayDiagnostic {
url: string;
connected: boolean;
requiresAuth: boolean;
error?: string;
responseTime?: number;
}
/**
* Tests connection to a single relay
*/
export async function testRelay(url: string): Promise<RelayDiagnostic> {
const startTime = Date.now();
return new Promise((resolve) => {
const ws = new WebSocket(url);
let resolved = false;
const timeout = setTimeout(() => {
if (!resolved) {
resolved = true;
ws.close();
resolve({
url,
connected: false,
requiresAuth: false,
error: "Connection timeout",
responseTime: Date.now() - startTime,
});
}
}, TIMEOUTS.RELAY_DIAGNOSTICS);
ws.onopen = () => {
if (!resolved) {
resolved = true;
clearTimeout(timeout);
ws.close();
resolve({
url,
connected: true,
requiresAuth: false,
responseTime: Date.now() - startTime,
});
}
};
ws.onerror = () => {
if (!resolved) {
resolved = true;
clearTimeout(timeout);
resolve({
url,
connected: false,
requiresAuth: false,
error: "WebSocket error",
responseTime: Date.now() - startTime,
});
}
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data[0] === "NOTICE" && data[1]?.includes("auth-required")) {
if (!resolved) {
resolved = true;
clearTimeout(timeout);
ws.close();
resolve({
url,
connected: true,
requiresAuth: true,
responseTime: Date.now() - startTime,
});
}
}
};
});
}
/**
* Tests all relays and returns diagnostic information
*/
export async function testAllRelays(): Promise<RelayDiagnostic[]> {
// Use the new relay management system
const allRelays = [...get(activeInboxRelays), ...get(activeOutboxRelays)];
console.log("[RelayDiagnostics] Testing", allRelays.length, "relays...");
const results = await Promise.allSettled(
allRelays.map((url) => testRelay(url)),
);
return results.map((result, index) => {
if (result.status === "fulfilled") {
return result.value;
} else {
return {
url: allRelays[index],
connected: false,
requiresAuth: false,
error: "Test failed",
};
}
});
}
/**
* Gets working relays from diagnostic results
*/
export function getWorkingRelays(diagnostics: RelayDiagnostic[]): string[] {
return diagnostics.filter((d) => d.connected).map((d) => d.url);
}
/**
* Logs relay diagnostic results to console
*/
export function logRelayDiagnostics(diagnostics: RelayDiagnostic[]): void {
console.group("[RelayDiagnostics] Results");
const working = diagnostics.filter((d) => d.connected);
const failed = diagnostics.filter((d) => !d.connected);
console.log(`✅ Working relays (${working.length}):`);
working.forEach((d) => {
console.log(
` - ${d.url}${d.requiresAuth ? " (requires auth)" : ""}${d.responseTime ? ` (${d.responseTime}ms)` : ""}`,
);
});
if (failed.length > 0) {
console.log(`❌ Failed relays (${failed.length}):`);
failed.forEach((d) => {
console.log(` - ${d.url}: ${d.error || "Unknown error"}`);
});
}
console.groupEnd();
}