use super::{cli, config, db, static_files, templates}; use handlebars::to_json; use serde::{Deserialize, Serialize}; use serde_json::value::{Map, Value as Json}; use sha2::{Digest, Sha512Trunc256}; use std::{ convert::TryInto, sync::{Arc, RwLock}, }; use warp::Filter; type PasswordHash = [u8; 32]; pub async fn start_server( config: config::Config, dbs: db::Dbs, templates: templates::Templates<'static>, opt: cli::MainOpt, ) { let templates = Arc::new(templates); let ads = vec![]; let mut data = Map::::new(); data.insert("lang".into(), to_json("fr")); data.insert("ads".into(), to_json(ads.clone())); let ads = Arc::new(RwLock::new(ads)); let data = Arc::new(RwLock::new(data)); let handle_index = { let data = data.clone(); move || { warp::reply::html( templates .hb .render("index.html", &*data.read().unwrap()) .unwrap_or_else(|e| e.to_string()), ) } }; let route_static = warp::path("static") .and(warp::get()) .and(warp::fs::dir(opt.dir.0.join(static_files::STATIC_DIR))); let route_index = warp::path::end() .and( warp::get() .map(handle_index.clone()) .or(warp::post() .and(warp::body::form::()) .map(move |ad: NewAdQuery| { let mut hasher = Sha512Trunc256::new(); hasher.update(ad.password); ads.write().unwrap().push(Ad { author: ad.author, password: hasher.finalize()[..].try_into().unwrap(), pubkey: (!ad.pubkey.is_empty()).then_some(ad.pubkey), time: 0, title: ad.title, }); data.write().unwrap().insert("ads".into(), to_json(&*ads.read().unwrap())); handle_index() }) ) ); warp::serve(route_static.or(route_index)) .run(config.listen) .await; } #[derive(Debug, Deserialize)] struct WotdQuery { wotd: String, } #[derive(Clone, Debug, Deserialize)] struct NewAdQuery { author: String, password: String, pubkey: String, title: String, } #[derive(Clone, Debug, Serialize)] struct Ad { author: String, password: PasswordHash, pubkey: Option, time: u64, title: String, }