// src/main.rs mod economic; mod corporate; mod config; mod util; use fantoccini::{ClientBuilder}; use serde_json::{Map, Value}; use tokio::signal; #[tokio::main] async fn main() -> anyhow::Result<()> { // === Ensure data directories exist === util::ensure_data_dirs().await?; // === Load configuration === let config = config::Config::default(); // === Start ChromeDriver === let mut child = std::process::Command::new("chromedriver-win64/chromedriver.exe") .args(["--port=9515"]) // Level 3 = minimal logs .spawn()?; // Build capabilities to hide infobar + enable full rendering let port = 9515; let caps_value = serde_json::json!({ "goog:chromeOptions": { "args": [ //"--headless", "--disable-gpu", "--disable-notifications", "--disable-popup-blocking", "--disable-blink-features=AutomationControlled" ], "excludeSwitches": ["enable-automation"] } }); let caps_map: Map = caps_value.as_object() .expect("Capabilities should be a JSON object") .clone(); let mut client = ClientBuilder::native() .capabilities(caps_map) .connect(&format!("http://localhost:{}", port)) .await?; // Graceful shutdown let client_clone = client.clone(); tokio::spawn(async move { signal::ctrl_c().await.unwrap(); client_clone.close().await.ok(); std::process::exit(0); }); // === Economic Calendar Update === println!("Updating Economic Calendar (High Impact Only)"); economic::goto_and_prepare(&client).await?; economic::run_full_update(&client, &config).await?; // === Corporate Earnings Update === println!("\nUpdating Corporate Earnings"); corporate::run_full_update(&client, &config).await?; // === Cleanup === client.close().await?; child.kill()?; println!("\nAll data updated successfully!"); Ok(()) }