// Minimal FlareSolverr client. FlareSolverr runs a headless browser that solves // Cloudflare's anti-bot challenge and returns the resolved page HTML. // https://github.com/FlareSolverr/FlareSolverr const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); // opts: { maxTimeout, cookies: [{ name, value, domain }], retries } async function solve(flaresolverrUrl, targetUrl, opts = {}) { const endpoint = flaresolverrUrl.replace(/\/+$/, '') + '/v1'; const body = { cmd: 'request.get', url: targetUrl, maxTimeout: opts.maxTimeout || 60000 }; if (opts.cookies) body.cookies = opts.cookies; // FlareSolverr serializes browser sessions and returns 500 on back-to-back // requests, so retry transient failures with a growing backoff. const retries = opts.retries ?? 4; let lastErr; for (let attempt = 0; attempt <= retries; attempt++) { if (attempt > 0) await sleep(2000 * attempt); try { const res = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); if (res.status >= 500) { lastErr = new Error(`FlareSolverr HTTP ${res.status}`); continue; } if (!res.ok) throw new Error(`FlareSolverr HTTP ${res.status}`); const data = await res.json(); if (data.status !== 'ok' || !data.solution) throw new Error(`FlareSolverr: ${data.message || 'no solution'}`); return data.solution.response; } catch (err) { lastErr = err; if (!/HTTP 5\d\d|fetch failed|ECONNRESET|network/i.test(err.message)) throw err; } } throw lastErr; } // Like solve(), but for endpoints that return JSON. A real browser wraps JSON // in a
 tag, so strip tags before parsing.
async function solveJson(flaresolverrUrl, targetUrl, opts = {}) {
  const html = await solve(flaresolverrUrl, targetUrl, opts);
  // The browser wraps JSON in 
 and HTML-encodes entities (notably & -> &
  // inside signed URLs), so strip tags and decode before parsing.
  const text = html.replace(/<[^>]*>/g, '')
    .replace(/"/g, '"').replace(/'/g, "'").replace(/</g, '<')
    .replace(/>/g, '>').replace(/&/g, '&')
    .trim();
  try {
    return JSON.parse(text);
  } catch {
    throw new Error('FlareSolverr did not return parseable JSON.');
  }
}

module.exports = { solve, solveJson };