181 lines
4.2 KiB
Rust
181 lines
4.2 KiB
Rust
use std::future;
|
|
|
|
use futures::{StreamExt, TryStreamExt};
|
|
use rocket_db_pools::mongodb::bson::to_bson;
|
|
|
|
use super::{prelude::*, util::PartyError};
|
|
|
|
use lan_party_core::event::*;
|
|
|
|
api_routes!(
|
|
create_event,
|
|
stop_event,
|
|
get_event,
|
|
update_event,
|
|
get_all_events,
|
|
event_outcome,
|
|
delete_event,
|
|
);
|
|
|
|
pub async fn apply_outcome(outcome: &EventOutcome, db: &Connection<Db>) -> Result<(), PartyError> {
|
|
for (player, reward) in outcome.points.iter() {
|
|
db.users()
|
|
.update_one(
|
|
doc! { "id": player.to_string() },
|
|
doc! { "$inc": { "score": reward } },
|
|
None,
|
|
)
|
|
.await?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// # Create event
|
|
///
|
|
/// Returns the created event.
|
|
#[openapi(tag = "Event")]
|
|
#[post("/", data = "<event>")]
|
|
pub async fn create_event(
|
|
_api_key: ApiKey,
|
|
db: Connection<Db>,
|
|
event: Json<EventSpec>,
|
|
) -> Result<Json<Event>, PartyError> {
|
|
let event = event.into_inner().create_event()?;
|
|
db.events().insert_one(&event, None).await?;
|
|
Ok(Json(event))
|
|
}
|
|
|
|
/// # Update event
|
|
///
|
|
/// Update the supplied values in the event with the given name. The `name` of an event cannot be
|
|
/// changed and `concluded` will always be false.
|
|
#[openapi(tag = "Event")]
|
|
#[post("/<name>", data = "<update>")]
|
|
pub async fn update_event(
|
|
_api_key: ApiKey,
|
|
db: Connection<Db>,
|
|
name: String,
|
|
update: Json<EventUpdate>,
|
|
) -> Result<Status, PartyError> {
|
|
let mut event = db
|
|
.events()
|
|
.find_one(doc! { "name": &name }, None)
|
|
.await?
|
|
.ok_or(PartyError::EventNotFound(name.clone()))?;
|
|
|
|
event.apply_update(update.into_inner())?;
|
|
|
|
db.events()
|
|
.update_one(
|
|
doc! { "name": &name },
|
|
doc! { "$set": to_bson(&event)? },
|
|
None,
|
|
)
|
|
.await?;
|
|
|
|
Ok(Status::Ok)
|
|
}
|
|
|
|
/// # Get event
|
|
///
|
|
/// Returns the event with the given name
|
|
#[openapi(tag = "Event")]
|
|
#[get("/<name>")]
|
|
pub async fn get_event(
|
|
_api_key: ApiKey,
|
|
db: Connection<Db>,
|
|
name: String,
|
|
) -> Result<Json<Event>, PartyError> {
|
|
Ok(Json(
|
|
db.events()
|
|
.find_one(doc! { "name": &name }, None)
|
|
.await?
|
|
.ok_or(PartyError::EventNotFound(name))?,
|
|
))
|
|
}
|
|
|
|
/// # Get events
|
|
///
|
|
/// Returns all events
|
|
#[openapi(tag = "Event")]
|
|
#[get("/?<concluded>")]
|
|
pub async fn get_all_events(
|
|
_api_key: ApiKey,
|
|
db: Connection<Db>,
|
|
concluded: Option<bool>,
|
|
) -> Result<Json<Vec<Event>>, PartyError> {
|
|
let filter = if let Some(concluded) = concluded {
|
|
doc! { "concluded": concluded }
|
|
} else {
|
|
doc! {}
|
|
};
|
|
Ok(Json(
|
|
db.events()
|
|
.find(filter, None)
|
|
.await?
|
|
.filter(|e| future::ready(e.is_ok()))
|
|
.try_collect()
|
|
.await?,
|
|
))
|
|
}
|
|
|
|
/// # Get outcome
|
|
///
|
|
/// Returns the outcome of an event.
|
|
#[openapi(tag = "Event")]
|
|
#[get("/<name>/outcome")]
|
|
pub async fn event_outcome(
|
|
_api_key: ApiKey,
|
|
db: Connection<Db>,
|
|
name: String,
|
|
) -> Result<Json<EventOutcome>, PartyError> {
|
|
let event = db
|
|
.events()
|
|
.find_one(doc! { "name": &name }, None)
|
|
.await?
|
|
.ok_or(PartyError::EventNotFound(name.clone()))?;
|
|
Ok(Json(event.outcome()))
|
|
}
|
|
|
|
/// # Stop event
|
|
///
|
|
/// This will conclude the event, apply the outcome to the users and return the outcome.
|
|
#[openapi(tag = "Event")]
|
|
#[post("/<name>/stop")]
|
|
pub async fn stop_event(
|
|
_api_key: ApiKey,
|
|
db: Connection<Db>,
|
|
name: String,
|
|
) -> Result<Json<EventOutcome>, PartyError> {
|
|
let event = db
|
|
.events()
|
|
.find_one(doc! { "name": &name }, None)
|
|
.await?
|
|
.ok_or(PartyError::EventNotFound(name.clone()))?;
|
|
event.conclude();
|
|
db.events()
|
|
.update_one(
|
|
doc! { "name": &name },
|
|
doc! { "$set": { "concluded": true } },
|
|
None,
|
|
)
|
|
.await?;
|
|
let outcome = event.outcome();
|
|
apply_outcome(&outcome, &db).await?;
|
|
|
|
Ok(Json(outcome))
|
|
}
|
|
|
|
/// # Delete event by name
|
|
#[openapi(tag = "Event")]
|
|
#[delete("/<name>")]
|
|
pub async fn delete_event(
|
|
_api_key: ApiKey,
|
|
db: Connection<Db>,
|
|
name: String,
|
|
) -> Result<Status, PartyError> {
|
|
db.events().delete_one(doc! { "name": name }, None).await?;
|
|
|
|
Ok(Status::Ok)
|
|
}
|