@@ -6,6 +6,7 @@
|
6 | 6 | */ |
7 | 7 | |
8 | 8 | import { SimplePool, verifyEvent, type Event } from "nostr-tools"; |
| 9 | +import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime"; |
9 | 10 | import type { NostrProfile } from "./config-schema.js"; |
10 | 11 | import { validateUrlSafety } from "./nostr-profile-url-safety.js"; |
11 | 12 | import { contentToProfile, type ProfileContent } from "./nostr-profile.js"; |
@@ -85,7 +86,8 @@ function sanitizeProfileUrls(profile: NostrProfile): NostrProfile {
|
85 | 86 | export async function importProfileFromRelays( |
86 | 87 | opts: ProfileImportOptions, |
87 | 88 | ): Promise<ProfileImportResult> { |
88 | | -const { pubkey, relays, timeoutMs = DEFAULT_TIMEOUT_MS } = opts; |
| 89 | +const { pubkey, relays } = opts; |
| 90 | +const timeoutMs = resolveTimerTimeoutMs(opts.timeoutMs, DEFAULT_TIMEOUT_MS); |
89 | 91 | |
90 | 92 | if (!pubkey || !/^[0-9a-fA-F]{64}$/.test(pubkey)) { |
91 | 93 | return { |
@@ -105,14 +107,21 @@ export async function importProfileFromRelays(
|
105 | 107 | |
106 | 108 | const pool = new SimplePool(); |
107 | 109 | const relaysQueried: string[] = []; |
| 110 | +const timers: Array<ReturnType<typeof setTimeout>> = []; |
| 111 | +const scheduleTimeout = (callback: () => void) => { |
| 112 | +const timer = setTimeout(callback, timeoutMs); |
| 113 | +timer.unref?.(); |
| 114 | +timers.push(timer); |
| 115 | +return timer; |
| 116 | +}; |
108 | 117 | |
109 | 118 | try { |
110 | 119 | // Query all relays for kind:0 events from this pubkey |
111 | 120 | const events: Array<{ event: Event; relay: string }> = []; |
112 | 121 | |
113 | 122 | // Create timeout promise |
114 | 123 | const timeoutPromise = new Promise<void>((resolve) => { |
115 | | -setTimeout(resolve, timeoutMs); |
| 124 | +scheduleTimeout(resolve); |
116 | 125 | }); |
117 | 126 | |
118 | 127 | // Create subscription promise |
@@ -147,14 +156,17 @@ export async function importProfileFromRelays(
|
147 | 156 | }); |
148 | 157 | |
149 | 158 | // Clean up subscription after timeout |
150 | | -setTimeout(() => { |
| 159 | +scheduleTimeout(() => { |
151 | 160 | sub.close(); |
152 | | -}, timeoutMs); |
| 161 | +}); |
153 | 162 | } |
154 | 163 | }); |
155 | 164 | |
156 | 165 | // Wait for either all relays to respond or timeout |
157 | 166 | await Promise.race([subscriptionPromise, timeoutPromise]); |
| 167 | +for (const timer of timers.splice(0)) { |
| 168 | +clearTimeout(timer); |
| 169 | +} |
158 | 170 | |
159 | 171 | // No events found |
160 | 172 | if (events.length === 0) { |
@@ -223,6 +235,9 @@ export async function importProfileFromRelays(
|
223 | 235 | sourceRelay: bestEvent.relay, |
224 | 236 | }; |
225 | 237 | } finally { |
| 238 | +for (const timer of timers) { |
| 239 | +clearTimeout(timer); |
| 240 | +} |
226 | 241 | pool.close(relays); |
227 | 242 | } |
228 | 243 | } |
|