use axum::extract::{Query, State}; use axum::{Router, routing::get}; use reqwest::Client; use serde::{Deserialize, Serialize}; use std::path::PathBuf; #[derive(Clone)] struct AppState { reqwest : Client, config : Config, } #[derive(Serialize, Debug)] struct Webhook { pub content : String, } #[derive(Deserialize, Debug, Clone)] struct Config { webhook_public : String, webhook_private : String, } impl Config { pub fn load(from : PathBuf) -> Config { toml::from_str( std::fs::read_to_string(from) .expect("failed to read config") .as_str(), ) .expect("failed to parse config") } } #[derive(Deserialize, Debug)] struct OpenCloseQueryParam { public : bool, } async fn handle_startup() { println!("can I haz button plz") } async fn handle_open(State(state) : State, query : Query) { state .reqwest .post( if query.public { state.config.webhook_public } else { state.config.webhook_private }, ) .json(&Webhook { content : "The space is now open!".to_string(), }) .send() .await .unwrap(); } async fn handle_close(State(state) : State, query : Query) { state .reqwest .post( if query.public { state.config.webhook_public } else { state.config.webhook_private }, ) .json(&Webhook { content : "The space is now closed!".to_string(), }) .send() .await .unwrap(); } #[tokio::main] async fn main() { let config = if cfg!(debug_assertions) { // use local config Config::load(PathBuf::from("config.toml")) } else { // now it's in docker, use the bind config! Config::load(PathBuf::from("/app/config.toml")) }; let state = AppState { reqwest : Client::new(), config, }; let app = Router::new() .route("/startup", get(handle_startup)) .route("/open", get(handle_open)) .route("/close", get(handle_close)) .with_state(state); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); axum::serve(listener, app).await.unwrap(); }