use crate::VoteHandler;
use axum::{
extract::State,
http::{HeaderMap, StatusCode},
response::{IntoResponse, Response},
routing::post,
Router,
};
use std::sync::Arc;
struct WebhookState<T> {
state: Arc<T>,
password: Arc<String>,
}
impl<T> Clone for WebhookState<T> {
#[inline(always)]
fn clone(&self) -> Self {
Self {
state: Arc::clone(&self.state),
password: Arc::clone(&self.password),
}
}
}
async fn handler<T>(
headers: HeaderMap,
State(webhook): State<WebhookState<T>>,
body: String,
) -> Response
where
T: VoteHandler,
{
if let Some(authorization) = headers.get("Authorization") {
if let Ok(authorization) = authorization.to_str() {
if authorization == *(webhook.password) {
if let Ok(vote) = serde_json::from_str(&body) {
webhook.state.voted(vote).await;
return (StatusCode::OK, ()).into_response();
}
}
}
}
(StatusCode::UNAUTHORIZED, ()).into_response()
}
#[inline(always)]
#[cfg_attr(docsrs, doc(cfg(feature = "axum")))]
pub fn webhook<T>(password: String, state: Arc<T>) -> Router
where
T: VoteHandler,
{
Router::new()
.route("/", post(handler::<T>))
.with_state(WebhookState {
state,
password: Arc::new(password),
})
}