function procesar_feed_individual( $feed_data ) { $args = array( 'timeout' => 15, 'redirection' => 3, 'httpversion' => '1.0', 'user-agent' => 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ), 'headers' => array( 'Accept' => 'application/rss+xml, application/xml, text/xml', 'Cache-Control' => 'no-cache' ) ); $response = wp_remote_get( $feed_data['url'], $args ); if ( is_wp_error( $response ) ) { return array( 'error' => 'Error de conexión: ' . $response->get_error_message() ); } $response_code = wp_remote_retrieve_response_code( $response ); if ( $response_code !== 200 ) { return array( 'error' => 'Error HTTP ' . $response_code . ': El servidor respondió con código de error. Posibles causas: URL incorrecta, sitio caído, o acceso restringido.' ); } $body = wp_remote_retrieve_body( $response ); if ( empty( $body ) ) { return array( 'error' => 'Respuesta vacía: El servidor no devolvió contenido. El feed puede estar vacío o temporalmente no disponible.' ); } // Limpiar el XML de caracteres problemáticos $body = trim( $body ); $body = preg_replace( '/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', '', $body ); libxml_use_internal_errors( true ); libxml_clear_errors(); $xml = simplexml_load_string( $body ); if ( false === $xml ) { $errors = libxml_get_errors(); $error_details = "Error al parsear XML.\n\nDetalles técnicos:\n"; if ( ! empty( $errors ) ) { foreach ( $errors as $error ) { $error_details .= "- Línea {$error->line}: {$error->message}"; } } $error_details .= "\nPrimeros 500 caracteres del contenido recibido:\n" . substr( $body, 0, 500 ); if ( strlen( $body ) > 500 ) { $error_details .= "\n... (contenido truncado)"; } $error_details .= "\n\nPosibles soluciones:\n"; $error_details .= "1. Verificar que la URL del RSS sea correcta\n"; $error_details .= "2. El sitio puede estar devolviendo HTML en lugar de XML\n"; $error_details .= "3. El feed puede tener caracteres especiales mal codificados\n"; $error_details .= "4. Problema temporal con el servidor del sitio"; return array( 'error' => $error_details ); } $noticias = array(); $items = array(); // Detectar tipo de feed if ( isset( $xml->channel->item ) ) { $items = $xml->channel->item; } elseif ( isset( $xml->item ) ) { $items = $xml->item; } elseif ( isset( $xml->entry ) ) { $items = $xml->entry; } if ( empty( $items ) ) { return array( 'error' => 'Feed válido pero vacío: El XML se parseó correctamente pero no contiene noticias. El feed puede estar temporalmente vacío.' ); } foreach ( $items as $item ) { if ( count( $noticias ) >= 10 ) break; // Máximo 10 por feed $titulo = ''; $enlace = ''; $fecha = ''; $descripcion = ''; if ( isset( $item->title ) ) { $titulo = (string) $item->title; } if ( isset( $item->link ) ) { $enlace = (string) $item->link; } elseif ( isset( $item->link['href'] ) ) { $enlace = (string) $item->link['href']; } if ( isset( $item->pubDate ) ) { $fecha = (string) $item->pubDate; } elseif ( isset( $item->published ) ) { $fecha = (string) $item->published; } elseif ( isset( $item->updated ) ) { $fecha = (string) $item->updated; } if ( isset( $item->description ) ) { $descripcion = (string) $item->description; } elseif ( isset( $item->summary ) ) { $descripcion = (string) $item->summary; } // Limpiar título $titulo = preg_replace( '/\s*-\s*[^-]*$/', '', $titulo ); $titulo = html_entity_decode( $titulo, ENT_QUOTES, 'UTF-8' ); $timestamp = strtotime( $fecha ); if ( ! $timestamp ) { $timestamp = time(); } // Fuente específica para Google News $fuente_especifica = $feed_data['nombre']; if ( strpos( $feed_data['url'], 'news.google.com' ) !== false && ! empty( $descripcion ) ) { if ( preg_match( '/([^<]+)<\/font>/', $descripcion, $matches ) ) { $fuente_especifica = trim( $matches[1] ); } } if ( ! empty( $titulo ) && ! empty( $enlace ) ) { $noticias[] = array( 'titulo' => $titulo, 'enlace' => $enlace, 'fecha' => $fecha, 'timestamp' => $timestamp, 'fuente' => $fuente_especifica, 'fuente_principal' => $feed_data['nombre'], 'color' => $feed_data['color'], 'categoria' => $feed_data['categoria'], 'descripcion' => strip_tags( $descripcion ) ); } } return $noticias; }