use clap::Parser; use hyper::service::{make_service_fn, service_fn}; use hyper::Server; use sqlx::sqlite::SqlitePool; use std::convert::Infallible; use std::net::SocketAddr; #[macro_use] extern crate log; mod assets; mod controller; mod crypto; mod db; mod jobs; mod mail; mod model; mod payer; mod queries; mod routes; mod templates; mod utils; mod validation; use model::config::Config; #[derive(Parser)] #[clap()] struct Args { #[clap(short, long, default_value = "0.0.0.0:3000")] address: SocketAddr, #[clap(short, long, default_value = "config.json")] config: String, #[clap(short, long, default_value = "database.db")] database: String, } #[tokio::main] async fn main() { env_logger::Builder::from_env( env_logger::Env::default().default_filter_or("warn"), ) .init(); let args = Args::parse(); let config_str = std::fs::read_to_string(&args.config) .unwrap_or_else(|_| panic!("{}", format!("Missing {}", args.config))); let config: Config = serde_json::from_str(&config_str).unwrap(); let pool = SqlitePool::connect(&format!("sqlite:{}", args.database)) .await .unwrap(); let assets = assets::get(); let templates = templates::get(); tokio::spawn(jobs::start(config.clone(), pool.clone(), templates.clone())); let make_svc = make_service_fn(|_conn| { let config = config.clone(); let pool = pool.clone(); let assets = assets.clone(); let templates = templates.clone(); async move { Ok::<_, Infallible>(service_fn(move |req| { routes::routes( config.clone(), pool.clone(), assets.clone(), templates.clone(), req, ) })) } }); info!("Starting server at {}", args.address); if let Err(e) = Server::bind(&args.address).serve(make_svc).await { error!("server error: {}", e); } }