#![feature(lazy_cell)] use std::collections::BTreeMap; use std::fs::File; use std::sync::Arc; use lfm_embed::{CONFIG, ResponseCtx}; use lfm_embed::cache::font::FontQuery; use log::LevelFilter; use dotenv::var; use warp::Filter; #[derive(serde::Deserialize, Debug)] #[serde(rename = "kebab-case")] struct UserQuery { #[serde(default)] theme: Option>, #[serde(flatten)] #[serde(default)] font: Option, #[serde(flatten)] rest: BTreeMap } #[tokio::main] async fn main() { env_logger::Builder::new() .filter_level(LevelFilter::Warn) .parse_filters(&var("LFME_LOG_LEVEL").unwrap_or_default()) .target( var("LFME_LOG_FILE").ok() .map( |f| env_logger::Target::Pipe( Box::new(File::options() .append(true) .open(f) .expect("couldn't open LFME_LOG_FILE"))) ) .unwrap_or(env_logger::Target::Stderr) ).init(); let user = warp::path!("user" / String) .and(warp::query::()) .then(|s, q: UserQuery| async move { log::debug!(target: "lfm_embed::server::user", "Handling request for user `{s}` with {q:?}"); let (ctx, dur) = lfm_embed::cache::user::get_userinfo(&s).await; let ResponseCtx(data, status) = ResponseCtx::create(ctx, q.font, q.rest).await; let theme = q.theme.filter(|a| CONFIG.handlebars().has_template(a)).unwrap_or_else(|| CONFIG.default_theme()); log::debug!(target: "lfm_embed::server::user", "Using theme {theme}"); warp::reply::with_header( warp::reply::with_header( warp::reply::with_status( warp::reply::html( CONFIG.handlebars().render(&theme, &data).unwrap() ), status ), "Refresh", dur.as_secs() ), "X-Selected-Theme", theme.as_ref() ) }); warp::serve(user) .bind(([127,0,0,1], CONFIG.port())).await; }