feat: handle open/close better

This commit is contained in:
Anna 2022-03-18 22:02:10 -04:00
parent c27fd8dacb
commit 6aa457f3d3
Signed by: anna
GPG Key ID: 0B391D8F06FCD9E0
7 changed files with 167 additions and 6 deletions

85
Cargo.lock generated
View File

@ -1262,6 +1262,33 @@ dependencies = [
"syn",
]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]]
name = "rustls"
version = "0.20.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921"
dependencies = [
"log",
"ring",
"sct",
"webpki",
]
[[package]]
name = "rustversion"
version = "1.0.6"
@ -1302,6 +1329,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "security-framework"
version = "2.6.1"
@ -1476,6 +1513,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "static_assertions"
version = "1.1.0"
@ -1616,6 +1659,17 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b"
dependencies = [
"rustls",
"tokio",
"webpki",
]
[[package]]
name = "tokio-stream"
version = "0.1.8"
@ -1648,8 +1702,12 @@ checksum = "06cda1232a49558c46f8a504d5b93101d42c0bf7f911f12a105ba48168f821ae"
dependencies = [
"futures-util",
"log",
"rustls",
"tokio",
"tokio-rustls",
"tungstenite 0.17.2",
"webpki",
"webpki-roots",
]
[[package]]
@ -1740,10 +1798,12 @@ dependencies = [
"httparse",
"log",
"rand",
"rustls",
"sha-1 0.10.0",
"thiserror",
"url",
"utf-8",
"webpki",
]
[[package]]
@ -1847,6 +1907,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "url"
version = "2.2.2"
@ -2015,6 +2081,25 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webpki"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "webpki-roots"
version = "0.22.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449"
dependencies = [
"webpki",
]
[[package]]
name = "winapi"
version = "0.3.9"

View File

@ -21,7 +21,7 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_with = { version = "1", features = ["chrono"] }
toml = "0.5"
tokio-tungstenite = { version = "0.17" }
tokio-tungstenite = { version = "0.17", features = ["rustls-tls-webpki-roots"] }
twitch_api2 = { version = "0.6.0-rc.3", features = ["twitch_oauth2", "client", "reqwest_client", "helix", "pubsub", "unsupported"] }
url = "2"
uuid = { version = "0.8", features = ["v4", "serde"] }

View File

@ -43,7 +43,7 @@ impl Twitch {
let mut user_token = self.config.read().await.user_token.as_ref().unwrap().clone();
if user_token.token.expires_in() <= std::time::Duration::from_secs(60 * 15) {
user_token.refresh_token(&reqwest::Client::new()).await?;
self.config.write().await.bot_token.replace(user_token.clone());
self.config.write().await.user_token.replace(user_token.clone());
}
Ok(user_token.token)

View File

@ -47,8 +47,8 @@ const REWARDS: &[RewardPauseInfo] = &[
];
const REQUIRE_OPEN_LIVESPLIT: &[&str] = &[
"7b66ffcd-8bd3-44c2-8d1d-3bc5ab1fa6ff",
"a598e71b-4521-4d74-8099-2859a81c4233",
"2205b59c-62d4-4dc1-bf27-2a96f3fcf2ca",
"3ea308c5-eeb8-4c46-88a5-d12555257b61",
];
async fn set_reward_paused(state: Arc<State>, id: String, paused: bool) -> anyhow::Result<()> {
@ -61,6 +61,7 @@ async fn set_reward_paused(state: Arc<State>, id: String, paused: bool) -> anyho
.build();
state.twitch.client.helix.req_patch(request, body, &state.twitch.user_token().await?).await?;
Ok(())
}

View File

@ -1,5 +1,5 @@
use twitch_api2::{
helix::points::{GetCustomRewardRequest, CustomReward},
helix::points::{CreateCustomRewardRequest, CreateCustomRewardBody, GetCustomRewardRequest, CustomReward},
types::RewardId,
};
use warp::{
@ -13,7 +13,7 @@ use crate::app::{
config::Redemption,
web::{
CustomRejection,
template::redemptions::{RedemptionsTemplate, AddRedemptionTemplate, ListRedemptionsTemplate},
template::redemptions::{RedemptionsTemplate, AddRedemptionTemplate, CreateRedemptionTemplate, ListRedemptionsTemplate},
},
};
use std::{
@ -28,10 +28,12 @@ pub fn redemptions_routes(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
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()
}
@ -94,6 +96,57 @@ fn redemptions_add_post(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
.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"))

View File

@ -17,3 +17,7 @@ pub struct AddRedemptionTemplate;
pub struct ListRedemptionsTemplate {
pub rewards: Vec<CustomReward>,
}
#[derive(Template)]
#[template(path = "create_redemption.html")]
pub struct CreateRedemptionTemplate;

View File

@ -0,0 +1,18 @@
{% extends "_base.html" %}
{% block title %}Create redemption{% endblock %}
{% block body %}
<ul class="breadcrumbs">
<li><a href="/">Home</a></li>
<li><a href="/redemptions">Redemptions</a></li>
<li><a href="/redemptions/add">Add</a></li>
<li><a href="/redemptions/list">List</a></li>
<li class="current"><a href="/redemptions/create">Create</a></li>
</ul>
<form action="/redemptions/create" method="post">
<input type="text" name="name" placeholder="Name"/>
<button type="submit">Create</button>
</form>
{% endblock %}