From d51c84997a7f0251867e98f13151dc70ce55a8d1 Mon Sep 17 00:00:00 2001 From: Ace Date: Tue, 23 Jun 2026 15:29:34 +0200 Subject: [PATCH] new changes --- rust-ai/src/main.rs | 56 ++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/rust-ai/src/main.rs b/rust-ai/src/main.rs index ed07239..ef33b3f 100644 --- a/rust-ai/src/main.rs +++ b/rust-ai/src/main.rs @@ -287,8 +287,8 @@ async fn handle_chat( if has_listing || (has_show && has_job) || (has_show && msg_lower.contains("links")) || msg_lower.contains("recent leads") { let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs(); let base_url = "http://localhost:3008/scrape/facebook"; - let mut req_builder = state.http_client.post(base_url).timeout(Duration::from_secs(300)); - + use std::fmt::Write; + let mut service_url = base_url.to_string(); if let Ok(Some((_, path))) = sqlx::query_as::<_, (uuid::Uuid, String)>( "SELECT id, profile_path FROM facebook_accounts \ WHERE is_active = TRUE AND flagged = FALSE \ @@ -297,27 +297,48 @@ async fn handle_chat( .fetch_optional(&state.db) .await { - req_builder = req_builder.query(&[("profile_path", &path), ("force", &"true".to_string())]); + let encoded: String = path.chars().map(|c| match c { + 'A'..='Z' | 'a'..='z' | '0'..='9' | '.' | '-' | '_' | '~' => c.to_string(), + _ => format!("%{:02X}", c as u8), + }).collect(); + write!(service_url, "?profile_path={}&force=true", encoded).unwrap(); + info!("Calling Python scrape at: {}?profile_path=...&force=true", base_url); } else { warn!("No active Facebook account found for on-demand scrape"); } + let req_builder = state.http_client.post(&service_url); match req_builder.send().await { Ok(resp) => { - if let Ok(scrape_resp) = resp.json::().await { - info!("Scraped {} leads from Facebook", scrape_resp.leads.len()); - let mut store = state.leads.lock().await; - for item in &scrape_resp.leads { - store.push(Lead { - title: truncate(&item.title, 120), - url: item.url.clone(), - source: item.source.clone().unwrap_or_else(|| "facebook".to_string()), - found_at: now, - author: truncate(&item.author, 60), - date: truncate(&item.date, 30), - content: truncate(&item.content, 300), - }); + let status = resp.status(); + let body = resp.text().await.unwrap_or_default(); + info!("Python scrape response ({}): {} bytes", status, body.len()); + if body.starts_with('{') { + match serde_json::from_str::(&body) { + Ok(scrape_resp) => { + info!("Scraped {} leads from Facebook", scrape_resp.leads.len()); + if scrape_resp.leads.is_empty() && scrape_resp.error.is_some() { + warn!("Python returned error: {:?}", scrape_resp.error); + } + let mut store = state.leads.lock().await; + for item in &scrape_resp.leads { + store.push(Lead { + title: truncate(&item.title, 120), + url: item.url.clone(), + source: item.source.clone().unwrap_or_else(|| "facebook".to_string()), + found_at: now, + author: truncate(&item.author, 60), + date: truncate(&item.date, 30), + content: truncate(&item.content, 300), + }); + } + } + Err(e) => { + warn!("Failed to parse Python scrape response: {} body: {}", e, &body[..body.len().min(200)]); + } } + } else { + warn!("Python returned non-JSON response: {}", &body[..body.len().min(200)]); } } Err(e) => { @@ -497,6 +518,9 @@ async fn main() { return; } }; + // Initial delay to let user on-demand requests take priority + tokio::time::sleep(Duration::from_secs(300)).await; + loop { // 10% random cycle skip — makes pattern non-periodic if rand::thread_rng().gen_range(0..100) < 10 {