230 lines
6.6 KiB
Rust
230 lines
6.6 KiB
Rust
use rocket::{
|
|
http::Status,
|
|
response::stream::{Event, EventStream},
|
|
tokio::{
|
|
self, select,
|
|
time::{self, sleep, Duration},
|
|
},
|
|
Route, Shutdown, State,
|
|
};
|
|
use rocket_dyn_templates::{context, Template};
|
|
|
|
use crate::global::{TrackedState::*, *};
|
|
|
|
#[get("/")]
|
|
fn no_id() -> Status {
|
|
Status::ImATeapot
|
|
}
|
|
|
|
#[get("/<id>?<gpslog>&<dbg>")]
|
|
fn tracked_view(
|
|
id: &str,
|
|
gpslog: Option<bool>,
|
|
dbg: Option<bool>,
|
|
tracking: &State<Tracking>,
|
|
) -> Result<Template, Status> {
|
|
if let Some(tracked) = tracking.get(&id.to_string()) {
|
|
Ok(Template::render(
|
|
match tracked.read().unwrap().state {
|
|
Vieux { .. } => "vieux",
|
|
Conscrit { .. } => "conscrit",
|
|
},
|
|
context! {
|
|
name: &tracked.read().unwrap().name,
|
|
id: &id,
|
|
gpslog: gpslog.unwrap_or(true),
|
|
dbg: dbg.unwrap_or(false),
|
|
},
|
|
))
|
|
} else {
|
|
Err(Status::BadRequest)
|
|
}
|
|
}
|
|
|
|
#[get("/<id>/events")]
|
|
fn tracked_events<'a>(
|
|
id: &'a str,
|
|
evt_queue: &'a State<TrackingEventQueue>,
|
|
config: &State<Config>,
|
|
mut shutdown: Shutdown,
|
|
) -> Result<EventStream![Event + 'a], Status> {
|
|
if evt_queue.contains_key(&id.to_string()) {
|
|
let timeout = Duration::from_millis(config.event_timeout);
|
|
Ok(EventStream! {
|
|
let mut interval = time::interval(timeout);
|
|
loop {
|
|
select!{
|
|
_ = interval.tick() =>{
|
|
for evt in evts_to_send(evt_queue.get(&id.to_string()).unwrap(), timeout){
|
|
//println!("{:?}", evt);
|
|
yield evt;
|
|
}
|
|
},
|
|
_ = &mut shutdown => break
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
Err(Status::BadRequest)
|
|
}
|
|
}
|
|
|
|
#[put("/<id>/pos?<lat>&<long>")]
|
|
fn store_pos(
|
|
id: &str,
|
|
lat: f32,
|
|
long: f32,
|
|
tracking: &State<Tracking>,
|
|
evt_queues: &State<TrackingEventQueue>,
|
|
admin_queue: &State<AdminEventQueue>,
|
|
) -> Status {
|
|
if let Some(tracked) = tracking.get(&id.to_string()) {
|
|
tracked.write().unwrap().pos = (lat, long);
|
|
state_update(&tracked.read().unwrap(), &evt_queues, &admin_queue);
|
|
Status::Accepted
|
|
} else {
|
|
Status::BadRequest
|
|
}
|
|
}
|
|
|
|
#[put("/<id>/state?<inv>&<col>")]
|
|
fn set_state(
|
|
id: &str,
|
|
inv: bool,
|
|
col: u8,
|
|
tracking: &State<Tracking>,
|
|
evt_queues: &State<TrackingEventQueue>,
|
|
admin_queue: &State<AdminEventQueue>,
|
|
) -> Status {
|
|
if let Some(tracked) = tracking.get(&id.to_string()) {
|
|
let tracked = &mut tracked.write().unwrap();
|
|
if let Vieux {
|
|
ref mut invisible,
|
|
ref mut color,
|
|
} = tracked.state
|
|
{
|
|
*invisible = inv;
|
|
*color = col;
|
|
state_update(&tracked, &evt_queues, &admin_queue);
|
|
Status::Accepted
|
|
} else {
|
|
Status::MethodNotAllowed
|
|
}
|
|
} else {
|
|
Status::BadRequest
|
|
}
|
|
}
|
|
|
|
#[put("/<id>/vanish")]
|
|
pub async fn activate_invisibility(
|
|
id: &str,
|
|
tracking: &State<Tracking>,
|
|
evt_queues: &State<TrackingEventQueue>,
|
|
admin_queue: &State<AdminEventQueue>,
|
|
config: &State<Config>,
|
|
) -> Status {
|
|
if let Some(tracked) = tracking.get(&id.to_string()) {
|
|
let tracked = &mut tracked.write().unwrap();
|
|
if let Conscrit {
|
|
ref mut invisible,
|
|
ref mut invisibility_codes,
|
|
..
|
|
} = tracked.state
|
|
{
|
|
if *invisibility_codes > 0 {
|
|
*invisibility_codes -= 1;
|
|
*invisible = true;
|
|
state_update(&tracked, &evt_queues, &admin_queue);
|
|
let track_clone = (*tracking).clone();
|
|
let queue_clone = (*evt_queues).clone();
|
|
let admin_clone = (*admin_queue).clone();
|
|
let id_str = id.to_string();
|
|
let timeout = Duration::from_millis(config.bonus_timeout);
|
|
tokio::spawn(async move {
|
|
sleep(timeout).await;
|
|
if let Conscrit {
|
|
ref mut invisible, ..
|
|
} = track_clone.get(&id_str).unwrap().write().unwrap().state
|
|
{
|
|
*invisible = false;
|
|
}
|
|
state_update(
|
|
&track_clone.get(&id_str).unwrap().read().unwrap(),
|
|
&queue_clone,
|
|
&admin_clone,
|
|
);
|
|
});
|
|
Status::Accepted
|
|
} else {
|
|
Status::PaymentRequired
|
|
}
|
|
} else {
|
|
Status::MethodNotAllowed
|
|
}
|
|
} else {
|
|
Status::BadRequest
|
|
}
|
|
}
|
|
|
|
#[put("/<id>/blur")]
|
|
pub async fn activate_blur(
|
|
id: &str,
|
|
tracking: &State<Tracking>,
|
|
evt_queues: &State<TrackingEventQueue>,
|
|
admin_queue: &State<AdminEventQueue>,
|
|
config: &State<Config>,
|
|
) -> Status {
|
|
if let Some(tracked) = tracking.get(&id.to_string()) {
|
|
let tracked = &mut tracked.write().unwrap();
|
|
if let Conscrit {
|
|
ref mut blurred,
|
|
ref mut blur_codes,
|
|
..
|
|
} = tracked.state
|
|
{
|
|
if *blur_codes > 0 {
|
|
*blur_codes -= 1;
|
|
*blurred = true;
|
|
state_update(&tracked, &evt_queues, &admin_queue);
|
|
let track_clone = (*tracking).clone();
|
|
let queue_clone = (*evt_queues).clone();
|
|
let admin_clone = (*admin_queue).clone();
|
|
let id_str = id.to_string();
|
|
let timeout = Duration::from_millis(config.bonus_timeout);
|
|
tokio::spawn(async move {
|
|
sleep(timeout).await;
|
|
if let Conscrit {
|
|
ref mut blurred, ..
|
|
} = track_clone.get(&id_str).unwrap().write().unwrap().state
|
|
{
|
|
*blurred = false;
|
|
}
|
|
state_update(
|
|
&track_clone.get(&id_str).unwrap().read().unwrap(),
|
|
&queue_clone,
|
|
&admin_clone,
|
|
);
|
|
});
|
|
Status::Accepted
|
|
} else {
|
|
Status::PaymentRequired
|
|
}
|
|
} else {
|
|
Status::MethodNotAllowed
|
|
}
|
|
} else {
|
|
Status::BadRequest
|
|
}
|
|
}
|
|
|
|
pub fn routes() -> Vec<Route> {
|
|
routes![
|
|
store_pos,
|
|
tracked_view,
|
|
tracked_events,
|
|
set_state,
|
|
activate_invisibility,
|
|
activate_blur,
|
|
no_id,
|
|
]
|
|
}
|