diff --git a/app/src/main/java/com/streamplayer/StreamUrlResolver.java b/app/src/main/java/com/streamplayer/StreamUrlResolver.java index 17a576b..e42f9f4 100644 --- a/app/src/main/java/com/streamplayer/StreamUrlResolver.java +++ b/app/src/main/java/com/streamplayer/StreamUrlResolver.java @@ -14,16 +14,15 @@ import okhttp3.Response; public final class StreamUrlResolver { // Múltiples patrones para extraer la URL del stream - // El proveedor cambia frecuentemente el formato private static final Pattern[] URL_PATTERNS = { - // Patrón original Pattern.compile("var\\s+playbackURL\\s*=\\s*[\"']([^\"']+)[\"']"), - // Alternativas comunes Pattern.compile("source\\s*:\\s*[\"']([^\"']+\\.m3u8[^\"']*)[\"']"), Pattern.compile("src\\s*:\\s*[\"']([^\"']+\\.m3u8[^\"']*)[\"']"), Pattern.compile("file\\s*:\\s*[\"']([^\"']+\\.m3u8[^\"']*)[\"']"), Pattern.compile("[\"'](https?://[^\"']+\\.m3u8[^\"']*)[\"']"), Pattern.compile("url\\s*:\\s*[\"']([^\"']+)[\"']"), + Pattern.compile("player\\s+src=\"([^\"]+)\""), + Pattern.compile("data-url=\"([^\"]+)\""), }; private StreamUrlResolver() { @@ -32,60 +31,84 @@ public final class StreamUrlResolver { public static String resolve(String pageUrl) throws IOException { String html = downloadPage(pageUrl); + // Verificar si es HTML válido o recibimos basura/compresión + if (!html.contains("<") && !html.contains(">")) { + // Probablemente respuesta comprimida o binaria + throw new IOException("El servidor devolvió una respuesta no válida. Posible bloqueo del ISP."); + } + // Intentar todos los patrones for (Pattern pattern : URL_PATTERNS) { Matcher matcher = pattern.matcher(html); if (matcher.find()) { String url = matcher.group(1); if (url != null && !url.isEmpty() && url.startsWith("http")) { - // Limpiar la URL si tiene caracteres de escape url = url.replace("\\", "").replace("&", "&"); return url; } } } - // Si no encontramos la URL, verificar si hay un mensaje de geobloqueo o similar - if (html.contains("Access Denied") || html.contains("403 Forbidden")) { - throw new IOException("Acceso bloqueado por el servidor. Posible geobloqueo o restricción de IP."); + // Verificar mensajes de error comunes en el HTML + String htmlLower = html.toLowerCase(); + + if (html.contains("Access Denied") || html.contains("403 Forbidden") || + htmlLower.contains("acceso denegado") || htmlLower.contains("access denied")) { + throw new IOException("Acceso bloqueado por el servidor. El proveedor del stream puede estar restringiendo el acceso desde tu ubicación."); } - if (html.contains("404") || html.contains("Not Found")) { - throw new IOException("Canal no encontrado (404). El canal puede estar temporalmente fuera de servicio."); + if (html.contains("404") || html.contains("Not Found") || + htmlLower.contains("no encontrado")) { + throw new IOException("Canal no disponible (404). El canal puede estar temporalmente fuera de servicio."); } - // Mostrar un fragmento del HTML para debug - String preview = html.length() > 800 ? html.substring(0, 800) : html; - throw new IOException("No se encontró la URL del stream. Vista previa: " + preview); + if (htmlLower.contains("maintenance") || htmlLower.contains("mantenimiento")) { + throw new IOException("El servidor está en mantenimiento. Intenta más tarde."); + } + + if (htmlLower.contains("banned") || htmlLower.contains("blocked") || + htmlLower.contains("bloqueado") || htmlLower.contains("suspendido")) { + throw new IOException("Acceso suspendido o bloqueado por el proveedor."); + } + + // Error genérico sin mostrar HTML crudo (evita símbolos extraños) + throw new IOException("No se pudo obtener el stream. El proveedor puede haber cambiado el formato o el canal está offline."); } private static String downloadPage(String pageUrl) throws IOException { Request request = new Request.Builder() .url(pageUrl) .header("User-Agent", NetworkUtils.getUserAgent()) - .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") + .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") .header("Accept-Language", "es-ES,es;q=0.9,en;q=0.8") - .header("Accept-Encoding", "gzip, deflate, br") .header("Referer", "https://streamtp10.com/") .header("Connection", "keep-alive") - .header("Upgrade-Insecure-Requests", "1") .build(); try (Response response = NetworkUtils.getClient().newCall(request).execute()) { if (!response.isSuccessful()) { if (response.code() == 403) { - throw new IOException("Acceso denegado (403). El servidor puede estar bloqueando tu conexión."); + throw new IOException("Acceso denegado (403). El servidor está bloqueando la conexión."); } else if (response.code() == 404) { throw new IOException("Canal no encontrado (404)."); + } else if (response.code() == 401) { + throw new IOException("Acceso no autorizado (401)."); } else { - throw new IOException("Error HTTP " + response.code() + " al cargar la página del stream"); + throw new IOException("Error HTTP " + response.code()); } } if (response.body() == null) { throw new IOException("Respuesta vacía del servidor"); } - return response.body().string(); + String body = response.body().string(); + + // Limitar tamaño para evitar problemas de memoria + if (body.length() > 500000) { + body = body.substring(0, 500000); + } + + return body; } } }