#![deny( warnings, nonstandard_style, unused, future_incompatible, rust_2018_idioms, unsafe_code )] #![deny(clippy::all, clippy::nursery, clippy::pedantic)] #![recursion_limit = "128"] #![allow(clippy::cast_precision_loss)] use {port_scanner::request_open_port, thirtyfour::error::WebDriverResult}; mod schedule; mod web; mod week; #[derive(serde::Serialize, serde::Deserialize)] struct Cache { schedule: schedule::MarkdownMap, last_updated: std::time::SystemTime, } #[tokio::main] async fn main() -> WebDriverResult<()> { let port = request_open_port().unwrap_or(9515); let cache = format!("{}/rin_cache", std::env::temp_dir().display()); if std::path::Path::new(&cache).exists() && std::env::var("RIN_CACHE_BUST").unwrap_or_else(|_| "0".to_string()) != "1" { let schedule: Cache = serde_json::from_str( &std::fs::read_to_string(&cache).expect("failed to read cache"), ) .expect("failed to parse cache"); if schedule .last_updated .elapsed() .unwrap() .as_secs() .checked_div(60) .unwrap() .checked_div(60) .unwrap() < 24 { schedule::render_markdown(&schedule.schedule).await; return Ok(()); } } let mut geckodriver = web::geckodriver(port).expect("failed to start geckodriver"); let driver = web::webdriver(port).await.expect("failed to start webdriver"); let markdown = schedule::to_markdown(&driver).await.expect("failed to get schedule"); let schedule = schedule::markdown_to_map(&markdown); std::fs::write( cache, serde_json::to_string(&Cache { schedule: schedule.clone(), last_updated: std::time::SystemTime::now(), }) .unwrap(), ) .unwrap(); schedule::render_markdown(&schedule).await; driver.quit().await.expect("failed to quit webdriver"); geckodriver.kill().await.expect("failed to kill geckodriver"); geckodriver.wait().await.expect("failed to wait for geckodriver"); Ok(()) }