// ¿Tiene el servidor salida a internet? Si las fuentes fallan por red, se comprueba contra varios sitios // a la vez; si ninguno responde, el servidor pasa a "sin conexión": las peticiones a las fuentes fallan // al instante (en vez de esperar timeouts y reintentos), las descargas y comprobaciones se pausan, y la // app trabaja solo con lo descargado. Mientras dure, se vuelve a comprobar cada poco y, al volver la // conexión, se reanuda todo solo. const PROBES = ['https://api.mangadex.org/ping', 'https://www.leercapitulo.co/', 'https://m440.in/', 'https://1.1.1.1/'] const EVERY_ONLINE = 3 * 60e3 const EVERY_OFFLINE = 20e3 export function setupConnectivity({ httpError }) { const state = { online: true, since: Date.now(), checkedAt: 0 } const onOnline = [] let probing = null // Cualquier respuesta HTTP (aunque sea un error) demuestra que hay internet. const probeOne = u => fetch(u, { method: 'HEAD', redirect: 'manual', signal: AbortSignal.timeout(6e3) }).then(() => true, () => false) function check() { probing ??= (async () => { const ok = (await Promise.all(PROBES.map(probeOne))).some(Boolean) state.checkedAt = Date.now() if (ok !== state.online) { state.online = ok state.since = Date.now() console.log(ok ? 'Conexión a internet recuperada: se reanudan descargas y comprobaciones.' : 'Sin conexión a internet: modo sin conexión (solo lo descargado).') if (ok) for (const f of onOnline) { try { f() } catch (e) { console.warn('Reconexión:', e.message) } } } return ok })().finally(() => { probing = null }) return probing } // Una fuente falló por red (no por un error HTTP): comprobar si es la fuente o es internet. function failed() { if (state.online && Date.now() - state.checkedAt > 10e3) check() } // Para cortar al instante las peticiones a las fuentes mientras no hay internet. function guard() { if (!state.online) throw httpError(503, 'El servidor no tiene conexión a internet: solo está disponible lo descargado.') } // Sin conexión: cada 20 s. En línea solo hace falta confirmar de vez en cuando (los fallos de red ya // disparan la comprobación). setInterval(() => { if (!state.online || Date.now() - state.checkedAt > EVERY_ONLINE) check().catch(() => {}) }, EVERY_OFFLINE).unref() check().catch(() => {}) return { online: () => state.online, status: () => ({ online: state.online, since: state.since, checkedAt: state.checkedAt }), check, failed, guard, whenOnline: f => onOnline.push(f), } }