use twitch_api2::types::RewardId; use warp::{ Filter, Reply, filters::BoxedFilter, http::Uri, }; use crate::app::{ State, config::Redemption, web::{ CustomRejection, template::redemptions::{RedemptionsTemplate, AddRedemptionTemplate}, }, }; use std::{ collections::HashMap, convert::Infallible, sync::Arc, }; pub fn redemptions_routes(state: Arc) -> BoxedFilter<(impl Reply, )> { warp::get() .and( redemptions_get(Arc::clone(&state)) .or(redemptions_add_get()) ) .or(warp::post().and( redemptions_add_post(Arc::clone(&state)) .or(redemptions_delete_post(Arc::clone(&state))) )) .boxed() } fn redemptions_get(state: Arc) -> BoxedFilter<(impl Reply, )> { warp::path("redemptions") .and(warp::path::end()) .and_then(move || { let state = Arc::clone(&state); async move { Result::::Ok(RedemptionsTemplate { redemptions: state.config.read().await.redemptions.clone(), }) } }) .boxed() } fn redemptions_add_get() -> BoxedFilter<(impl Reply, )> { warp::path("redemptions") .and(warp::path("add")) .and(warp::path::end()) .map(|| AddRedemptionTemplate) .boxed() } fn redemptions_add_post(state: Arc) -> BoxedFilter<(impl Reply, )> { warp::path("redemptions") .and(warp::path("add")) .and(warp::path::end()) .and(warp::body::content_length_limit(1024 * 5)) .and(warp::body::form()) .and_then(move |mut form: HashMap| { let state = Arc::clone(&state); async move { let form_get = try { let name = form.remove("name")?; let twitch_id = form.remove("twitch_id")?; let rhai = form.remove("rhai")?; (name, twitch_id, rhai) }; let (name, twitch_id, rhai) = match form_get { Some(x) => x, None => return Err(warp::reject::custom(CustomRejection::InvalidForm)), }; let redemption = Redemption { name, twitch_id: RewardId::new(twitch_id), rhai, }; state.config.write().await.redemptions.push(redemption); Ok(warp::redirect(Uri::from_static("/redemptions"))) } }) .boxed() } fn redemptions_delete_post(state: Arc) -> BoxedFilter<(impl Reply, )> { warp::path("redemptions") .and(warp::path("delete")) .and(warp::path::end()) .and(warp::body::content_length_limit(1024 * 5)) .and(warp::body::form()) .and_then(move |mut form: HashMap| { let state = Arc::clone(&state); async move { let name = match form.remove("name") { Some(n) => n, None => return Err(warp::reject::custom(CustomRejection::InvalidForm)), }; state.config.write().await.redemptions.drain_filter(|redemption| redemption.name == name); Ok(warp::redirect(Uri::from_static("/redemptions"))) } }) .boxed() }