198 lines
6.7 KiB
Rust
198 lines
6.7 KiB
Rust
use twitch_api2::{
|
|
helix::points::{CreateCustomRewardRequest, CreateCustomRewardBody, GetCustomRewardRequest, CustomReward},
|
|
types::RewardId,
|
|
};
|
|
use warp::{
|
|
Filter, Reply,
|
|
filters::BoxedFilter,
|
|
http::Uri,
|
|
};
|
|
use uuid::Uuid;
|
|
use crate::app::{
|
|
State,
|
|
config::Redemption,
|
|
web::{
|
|
CustomRejection,
|
|
template::redemptions::{RedemptionsTemplate, AddRedemptionTemplate, CreateRedemptionTemplate, ListRedemptionsTemplate},
|
|
},
|
|
};
|
|
use std::{
|
|
collections::HashMap,
|
|
convert::Infallible,
|
|
sync::Arc,
|
|
};
|
|
|
|
pub fn redemptions_routes(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
|
warp::get()
|
|
.and(
|
|
redemptions_get(Arc::clone(&state))
|
|
.or(redemptions_add_get())
|
|
.or(redemptions_list_get(Arc::clone(&state)))
|
|
.or(redemptions_create_get())
|
|
)
|
|
.or(warp::post().and(
|
|
redemptions_add_post(Arc::clone(&state))
|
|
.or(redemptions_delete_post(Arc::clone(&state)))
|
|
.or(redemptions_create_post(Arc::clone(&state)))
|
|
))
|
|
.boxed()
|
|
}
|
|
|
|
fn redemptions_get(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
|
warp::path("redemptions")
|
|
.and(warp::path::end())
|
|
.and_then(move || {
|
|
let state = Arc::clone(&state);
|
|
async move {
|
|
Result::<RedemptionsTemplate, Infallible>::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<State>) -> 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<String, String>| {
|
|
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 {
|
|
id: Uuid::new_v4(),
|
|
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_create_get() -> BoxedFilter<(impl Reply, )> {
|
|
warp::path("redemptions")
|
|
.and(warp::path("create"))
|
|
.and(warp::path::end())
|
|
.map(|| CreateRedemptionTemplate)
|
|
.boxed()
|
|
}
|
|
|
|
fn redemptions_create_post(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
|
warp::path("redemptions")
|
|
.and(warp::path("create"))
|
|
.and(warp::path::end())
|
|
.and(warp::body::content_length_limit(1024 * 5))
|
|
.and(warp::body::form())
|
|
.and_then(move |mut form: HashMap<String, String>| {
|
|
let state = Arc::clone(&state);
|
|
async move {
|
|
let form_get = try {
|
|
let name = form.remove("name")?;
|
|
name
|
|
};
|
|
|
|
let name = match form_get {
|
|
Some(x) => x,
|
|
None => return Err(warp::reject::custom(CustomRejection::InvalidForm)),
|
|
};
|
|
|
|
let request = CreateCustomRewardRequest::builder()
|
|
.broadcaster_id(state.user_config.twitch.channel_id.to_string())
|
|
.build();
|
|
|
|
let body = CreateCustomRewardBody::builder()
|
|
.title(name)
|
|
.cost(100)
|
|
.build();
|
|
|
|
let token = match state.twitch.user_token().await {
|
|
Ok(token) => token,
|
|
Err(_) => return Err(warp::reject::custom(CustomRejection::TwitchError)),
|
|
};
|
|
let _reward: CustomReward = match state.twitch.client.helix.req_post(request, body, &token).await {
|
|
Ok(resp) => resp.data,
|
|
Err(_) => return Err(warp::reject::custom(CustomRejection::TwitchError)),
|
|
};
|
|
|
|
Ok(warp::redirect(Uri::from_static("/redemptions/list")))
|
|
}
|
|
})
|
|
.boxed()
|
|
}
|
|
|
|
fn redemptions_delete_post(state: Arc<State>) -> 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<String, String>| {
|
|
let state = Arc::clone(&state);
|
|
async move {
|
|
let id = match super::uuid_from_form(&mut form) {
|
|
Some(n) => n,
|
|
None => return Err(warp::reject::custom(CustomRejection::InvalidForm)),
|
|
};
|
|
|
|
state.config.write().await.redemptions.drain_filter(|redemption| redemption.id == id);
|
|
|
|
Ok(warp::redirect(Uri::from_static("/redemptions")))
|
|
}
|
|
})
|
|
.boxed()
|
|
}
|
|
|
|
fn redemptions_list_get(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
|
warp::path("redemptions")
|
|
.and(warp::path("list"))
|
|
.and(warp::path::end())
|
|
.and_then( move || {
|
|
let state = Arc::clone(&state);
|
|
async move {
|
|
let req = GetCustomRewardRequest::builder()
|
|
.broadcaster_id(state.user_config.twitch.channel_id.to_string())
|
|
.build();
|
|
let token = match state.twitch.user_token().await {
|
|
Ok(token) => token,
|
|
Err(_) => return Err(warp::reject::custom(CustomRejection::TwitchError)),
|
|
};
|
|
let rewards: Vec<CustomReward> = match state.twitch.client.helix.req_get(req, &token).await {
|
|
Ok(resp) => resp.data,
|
|
Err(_) => return Err(warp::reject::custom(CustomRejection::TwitchError)),
|
|
};
|
|
Ok(rewards)
|
|
}
|
|
})
|
|
.map(|rewards: Vec<CustomReward>| ListRedemptionsTemplate {
|
|
rewards,
|
|
})
|
|
.boxed()
|
|
}
|