// scripts/lib/botPhoneApi.js // // Route phone probes through the running bot's HTTP API when the CLI // process has no attached relay WebSocket (normal for local scripts). export function botApiBase() { return (process.env.PROBE_PHONE_API_BASE || process.env.BOT_API_BASE || `http://localhost:${process.env.SERVER_PORT || 1800}`).replace(/\/$/, ''); } export function localRelayConnected(getDectRelayHub) { try { return getDectRelayHub().isConnected(); } catch { return false; } } export async function botApiFetch(path) { const token = process.env.HTTP_API_TOKEN; const headers = token ? { Authorization: `Bearer ${token}` } : {}; const url = `${botApiBase()}${path}`; let res; try { res = await fetch(url, { headers }); } catch (err) { const hint = 'Start the bot (node index.js) so the relay WebSocket is attached, or set PROBE_PHONE_API_BASE to a running instance.'; const e = new Error(`Cannot reach bot API at ${url} — ${err.message}. ${hint}`); e.code = 'BOT_API_UNREACHABLE'; e.cause = err; throw e; } const body = await res.json().catch(() => ({})); if (!res.ok) { const err = new Error(body?.message || `bot API ${res.status} ${path}`); err.code = body?.code || 'BOT_API_ERROR'; err.body = body; throw err; } return body; } export function mapApiPhoneToProbeResult(target, phoneRow) { return { phone: target, ok: !!phoneRow?.ok, probes: phoneRow?.probes || null, statusJson: phoneRow?.statusJson || null, statusXml: phoneRow?.statusXml || null, parsed: phoneRow?.parsed || null, verdict: phoneRow?.verdict || null, summary: phoneRow?.summary || null, cfgParsed: phoneRow?.cfgParsed || null, byteLength: phoneRow?.byteLength || null, elapsedMs: phoneRow?.elapsedMs || null, error: phoneRow?.error || null, }; } export async function probeTargetsViaBotApi(targets) { const results = []; let relay = { connected: false }; for (const t of targets) { const data = await botApiFetch(`/api/phone/probe-direct/${encodeURIComponent(t.ip)}`); relay = data.relay || relay; results.push(mapApiPhoneToProbeResult(t, data.phones?.[0])); } return { results, relay }; } export async function captureStoreViaBotApi(store, { ip } = {}) { const qs = ip ? `?ip=${encodeURIComponent(ip)}` : ''; return botApiFetch(`/api/phone/probe/${store}${qs}`); }