use std::fs; use std::path::{Path, PathBuf}; use serde::Deserialize; #[derive(Deserialize)] struct ConfigFile { site_title: Option, data_dir: Option, external_root: Option, listen_port: Option, footer_copyright: Option, } pub struct Config { pub site_title: String, pub data_dir: PathBuf, pub external_root: String, pub listen_port: u16, pub footer_copyright: Option, } impl Config { pub fn read_from_file() -> Result { let config_path = Self::get_location()?; let config_contents = fs::read_to_string(&config_path) .map_err(|_| "Unable to open config file".to_string())?; let file: ConfigFile = toml::from_str(&config_contents).map_err(|err| err.to_string())?; let port = file.listen_port.unwrap_or(3000); Ok(Self { site_title: file .site_title .unwrap_or("Untitled StormScribe Site".to_string()), data_dir: file.data_dir.unwrap_or( PathBuf::from(&config_path) .canonicalize() .map_err(|_| "Cannot resolve config file location".to_string())? .parent() .ok_or("Cannot resolve data dir".to_string())? .to_path_buf(), ), external_root: file .external_root .unwrap_or(format!("http://localhost:{port}/")), listen_port: port, footer_copyright: file.footer_copyright, }) } fn get_location() -> Result { Ok( std::env::var("STORMSCRIBE_CONFIG_FILE").or_else(|_| -> Result { Ok(std::path::Path::join( &std::env::current_dir() .map_err(|_| "Could not read current directory".to_string())?, "config.toml", ) .to_string_lossy() .to_string()) })?, ) } }