use std::time::Duration; use chrono::DateTime; use tokio::{sync::Mutex, time::Instant}; use crate::api::{bahnhof_get_departures, ApiClient}; pub struct Cache { pub index: String, pub nojs: String, pub data: Mutex, api_client: Mutex, api_next_update: Mutex, pub bahnhof_html: Mutex, bahnhof_next_update: Mutex, } pub struct Data { pub seq: u8, pub departures: Vec, // pub changes: [Vec; 10], } #[derive(Debug)] pub struct Departure { pub route_name: Option, pub departure_direction_text: Option, pub vehicle_number: Option, pub departure_time: Option>, pub scheduled_time: Option>, pub direction: Option, } impl Cache { pub fn new(index: String, nojs: String, swu_stop_number: Option) -> Self { let now = Instant::now(); Self { index, nojs, data: Mutex::new(Data { seq: 0, departures: vec![], }), api_client: Mutex::new(if let Some(swu_stop_number) = swu_stop_number { ApiClient::new_custom(swu_stop_number) } else { ApiClient::new() }), api_next_update: Mutex::new(now), bahnhof_html: Mutex::new(String::new()), bahnhof_next_update: Mutex::new(now), } } pub async fn update_swu(&self) -> Duration { let mut next_update = self.api_next_update.lock().await; let now = Instant::now(); if now >= *next_update { let delay = Duration::from_secs(14); let mut api = self.api_client.lock().await; match api.api_get().await { Ok(()) => { // TODO: find changes // increment sequence number thingy (ze counting boi) let mut data = self.data.lock().await; data.seq += 1; if data.seq >= 10 { data.seq = 0; } // store departures let departures = api .departures .iter() .map(|departure| { let direction = departure .route_name .as_ref() .and_then(|rn| { departure.departure_direction_text.as_ref().and_then(|dt| { api.directions .get(rn) .and_then(|v| v.get(dt).and_then(|v| v.as_ref())) }) }) .filter(|(_, _, success)| *success > 2) .map(|(_, dir, _)| *dir); Departure { route_name: departure.route_name.clone(), departure_direction_text: departure .departure_direction_text .clone(), vehicle_number: departure.vehicle_number, departure_time: departure .departure_time_actual .as_ref() .or(departure.departure_time_scheduled.as_ref()) .cloned(), scheduled_time: departure.departure_time_scheduled.clone(), direction, } }) .collect(); data.departures = departures; } Err(e) => eprintln!("Couldn't get departures from swu: {e}"), } *next_update = Instant::now() + delay; delay } else { *next_update - now } } pub async fn update_bahn(&self) -> Duration { let mut next_update = self.bahnhof_next_update.lock().await; let now = Instant::now(); if now >= *next_update { let delay = Duration::from_secs(59); // bahnhof api request match bahnhof_get_departures().await { Ok(v) => { *self.bahnhof_html.lock().await = v; } Err(e) => eprintln!("Couldn't get departures from bahnhof: {e}"), } *next_update = Instant::now() + delay; delay } else { *next_update - now } } }