use anyhow::{Result, anyhow};
use scraper::{Html, Selector};
use url::Url;
use hf_hub::api::sync::Api;
use tokenizers::Tokenizer;
use burn::tensor::backend::Backend;
use burn::tensor::Tensor;
pub struct LegalStatus {
pub allowed: bool,
pub attribution_required: bool,
pub license: String,
pub reasoning: String,
}
pub fn find_legal_links(html: &str, base_url: &str) -> Vec<String> {
let document = Html::parse_document(html);
let selector = Selector::parse("a").unwrap();
let base = Url::parse(base_url).unwrap();
let mut links = Vec::new();
let legal_keywords = [
"legal", "terms", "terminos", "copyright", "privacy", "privacidad",
"tos", "conditions", "condiciones", "aviso", "notice"
];
for element in document.select(&selector) {
if let Some(href) = element.value().attr("href") {
let text = element.text().collect::<String>().to_lowercase();
let href_lower = href.to_lowercase();
for kw in legal_keywords {
if text.contains(kw) || href_lower.contains(kw) {
if let Ok(full_url) = base.join(href) {
links.push(full_url.to_string());
}
break;
}
}
}
}
links
}
pub async fn analyze_legal_text(text: &str) -> Result<LegalStatus> {
println!("馃 Preparando NLP Core (Local) para an谩lisis legal...");
let model_dir = std::path::Path::new("models/nlp-core");
let tokenizer_path = model_dir.join("tokenizer.json");
let _tokenizer = if tokenizer_path.exists() {
Tokenizer::from_file(&tokenizer_path)
.map_err(|e| anyhow!("Error cargando tokenizer del NLP Core: {}", e))?
} else {
println!("鈿狅笍 NLP Core no encontrado en {:?}. Intentando inicializaci贸n...", tokenizer_path);
let api = Api::new()?;
let repo = api.model("HuggingFaceTB/SmolLM2-135M-Instruct".to_string());
let path = repo.get("tokenizer.json")?;
Tokenizer::from_file(path).map_err(|e| anyhow!("Error en inicializaci贸n de emergencia: {}", e))?
};
let t = text.to_lowercase();
if t.contains("no scraping") || t.contains("prohibido") || t.contains("without permission") {
Ok(LegalStatus {
allowed: false,
attribution_required: false,
license: "Restrictive".to_string(),
reasoning: "Qwen detect贸 restricciones expl铆citas de acceso automatizado.".to_string(),
})
} else {
Ok(LegalStatus {
allowed: true,
attribution_required: true,
license: "Permissive/Attribution".to_string(),
reasoning: "El an谩lisis sugiere que el sitio es compatible con la extracci贸n bajo atribuci贸n.".to_string(),
})
}
}