129 lines
4.8 KiB
Rust
129 lines
4.8 KiB
Rust
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<Data>,
|
|
pub api_client: Mutex<ApiClient>,
|
|
pub api_next_update: Mutex<Instant>,
|
|
pub bahnhof_html: Mutex<String>,
|
|
pub bahnhof_next_update: Mutex<Instant>,
|
|
}
|
|
pub struct Data {
|
|
pub seq: u8,
|
|
pub departures: Vec<Departure>,
|
|
// pub changes: [Vec<Change>; 10],
|
|
}
|
|
#[derive(Debug)]
|
|
pub struct Departure {
|
|
pub route_name: Option<String>,
|
|
pub departure_direction_text: Option<String>,
|
|
pub vehicle_number: Option<u32>,
|
|
pub departure_time: Option<DateTime<chrono::Local>>,
|
|
pub scheduled_time: Option<DateTime<chrono::Local>>,
|
|
pub direction: Option<i32>,
|
|
}
|
|
impl Cache {
|
|
pub fn new(index: String, nojs: String, swu_stop_number: Option<u32>) -> 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
|
|
}
|
|
}
|
|
}
|