105 lines
2.8 KiB
Rust
105 lines
2.8 KiB
Rust
#![feature(proc_macro_hygiene, decl_macro)]
|
|
|
|
#[macro_use]
|
|
extern crate rocket;
|
|
|
|
#[macro_use]
|
|
extern crate anyhow;
|
|
|
|
use rocket::{http::RawStr, State};
|
|
use std::{
|
|
collections::BTreeMap,
|
|
fmt::Display,
|
|
sync::{Arc, Mutex},
|
|
time::{Duration, SystemTime},
|
|
};
|
|
|
|
#[derive(Default)]
|
|
struct LoggedAccesses {
|
|
devices: BTreeMap<String, DeviceLog>,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct DeviceLog {
|
|
access_times: Vec<SystemTime>,
|
|
}
|
|
|
|
impl LoggedAccesses {
|
|
pub fn log_device_access(&mut self, device_name: &str) {
|
|
let device = self.devices.entry(String::from(device_name)).or_default();
|
|
|
|
let now = SystemTime::now();
|
|
device.access_times.push(now)
|
|
}
|
|
}
|
|
|
|
impl DeviceLog {
|
|
pub fn get_duration(&self) -> Result<(Duration, &SystemTime, &SystemTime), anyhow::Error> {
|
|
let start = self.access_times.first().ok_or(anyhow!("No start time"))?;
|
|
let end = self.access_times.last().ok_or(anyhow!("No end time"))?;
|
|
|
|
let duration = end
|
|
.duration_since(start.clone())
|
|
.map_err(|_| anyhow!("Times could not be diffed"))?;
|
|
|
|
Ok((duration, &start, &end))
|
|
}
|
|
}
|
|
|
|
impl Display for LoggedAccesses {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
for (device_name, device_log) in &self.devices {
|
|
f.write_fmt(format_args!("{}: {}\n", device_name, device_log))?
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Display for DeviceLog {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self.get_duration() {
|
|
Ok((duration, start, end)) => f.write_fmt(format_args!(
|
|
"{} seconds between first ({:?}) and last ({:?}) call",
|
|
duration.as_secs(),
|
|
start,
|
|
end
|
|
)),
|
|
Err(e) => f.write_fmt(format_args!("Error getting duration: {}", e)),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[get("/")]
|
|
fn index(state: State<Arc<Mutex<LoggedAccesses>>>) -> Result<String, anyhow::Error> {
|
|
match state.clone().lock() {
|
|
Ok(logged_accesses) => Ok(format!(
|
|
"Devices:\n{}\n\nwhile true; do curl https://pc.vvn.space/log/name; sleep 5; done",
|
|
logged_accesses
|
|
)),
|
|
Err(_) => Err(anyhow!("Couldn't lock state")),
|
|
}
|
|
}
|
|
|
|
#[get("/log/<device_name>")]
|
|
fn log(
|
|
device_name: &RawStr,
|
|
state: State<Arc<Mutex<LoggedAccesses>>>,
|
|
) -> Result<String, anyhow::Error> {
|
|
match &mut state.clone().lock() {
|
|
Ok(logged_accesses) => {
|
|
logged_accesses.log_device_access(device_name);
|
|
Ok(String::from("Logged"))
|
|
}
|
|
Err(_) => Err(anyhow!("Couldn't lock state")),
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
rocket::ignite()
|
|
.manage(Arc::<Mutex<LoggedAccesses>>::default())
|
|
.mount("/", routes![index, log])
|
|
.launch();
|
|
|
|
println!("after");
|
|
}
|