mod html; mod middleware; mod pages; use actix_web::{App, HttpServer, web}; use clap::Parser; use serde::Deserialize; use sqlx::PgPool; use std::fs::File; use std::io::Read; use std::process::exit; use toml::from_slice; use crate::pages::files::robots; use middleware::MimeType; use pages::{ files::file, index, music::music, projects::{project, projects}, }; #[derive(Parser)] #[command(name = "aindustries-be", version, about = "This is the amazing webserver for aindustries.be!", long_about = None)] struct Cli { #[arg( short, long, value_name = "CONFIG", help = "Path to config file, defaults to /etc/aindustries-be/config.toml" )] config: Option, } #[derive(Deserialize)] struct Config { server: ServerConfig, database: DatabaseConfig, } #[derive(Deserialize)] struct ServerConfig { assets: String, bind: String, } #[derive(Deserialize)] struct DatabaseConfig { address: String, user: String, password: String, database_name: String, } struct AppState { assets: String, pool: PgPool, } #[actix_web::main] async fn main() { let cli = Cli::parse(); let config_file_path = cli .config .unwrap_or("/etc/aindustries-be/config.toml".to_string()); let mut config_file = match File::open(&config_file_path) { Ok(config_file) => config_file, Err(e) => { eprintln!("Could not open config file ({config_file_path}): {e}"); exit(1); } }; let mut buf = vec![]; if let Err(e) = config_file.read_to_end(&mut buf) { eprintln!("Could not read config file: {e}"); exit(1); } let config: Config = match from_slice(&buf) { Ok(config) => config, Err(e) => { eprintln!("Could not parse config file {e}"); exit(1); } }; let bind_address = config.server.bind; let assets = config.server.assets; let database_address = format!( "postgres://{}:{}@{}/{}", config.database.user, config.database.password, config.database.address, config.database.database_name ); let pool = match PgPool::connect(&database_address).await { Ok(pool) => pool, Err(e) => { eprintln!("Could not connect to database: {e}"); exit(1); } }; let assets = assets.replace("~", "/home/conta/Code/aindustries.be/assets"); let data = web::Data::new(AppState { assets, pool }); if let Ok(server) = HttpServer::new(move || { App::new() .app_data(data.clone()) .service(file) .service(robots) .service( web::scope("") .wrap(MimeType::new("text/html")) .service(index) .service(projects) .service(project) .service(music), ) }) .bind(bind_address) { match server.run().await { Ok(_) => {} Err(e) => { eprintln!("An error occurred: {e}"); } } } }