use std::collections::BTreeSet; use std::sync::LazyLock; use std::sync::Arc; use std::time::*; use dotenv::var; use duration_str as ds; pub static CONFIG: LazyLock> = LazyLock::new(|| { Config::new() }); #[derive(Debug)] pub struct Config { pub(crate) google_api_key: Option>, pub(crate) lastfm_api_key: Arc, port: u16, send_refresh_header: bool, pub(crate) default_theme: Arc, pub(crate) theme_dir: Option>, pub(crate) theme_ext: Arc, pub(crate) theme_debug: bool, pub(crate) whitelist: BTreeSet, pub(crate) whitelist_mode: String, pub(crate) default_refresh: Duration, pub(crate) whitelist_refresh: Duration, } impl Config { fn new() -> Arc { let duration_from_var = |v: &str, d: u64| -> Duration {var(v).map(|r| ds::parse(&r).expect("bad duration string")).unwrap_or_else(|_| Duration::from_secs(d))}; let default_refresh = duration_from_var("LFME_DEFAULT_REFRESH", 300); let whitelist_refresh = duration_from_var("LFME_WHITELIST_REFRESH", 60); Arc::new(Config { lastfm_api_key: var("LFME_LASTFM_API_KEY").expect("last.fm API key must be set").into(), google_api_key: var("LFME_GOOGLE_API_KEY").map(Into::into).ok(), port: var("LFME_PORT").map(|p| p.parse().expect("cannot parse as a port number")).unwrap_or(9999), send_refresh_header: !var("LFME_NO_REFRESH").map(|h| &h == "1").unwrap_or(false), default_theme: var("LFME_THEME_DEFAULT").map(Into::into).unwrap_or_else(|_| "plain".into()), theme_dir: var("LFME_THEME_DIR").ok().map(Into::into), theme_ext: var("LFME_THEME_EXT").unwrap_or_else(|_| ".hbs".into()).into(), theme_debug: var("LFME_THEME_DEV").map(|h| &h == "1").unwrap_or(false), whitelist: var("LFME_WHITELIST").ok().map(|w| w.split(',').map(|s| s.trim().to_string()).collect()).unwrap_or_default(), whitelist_mode: var("LFME_WHITELIST_MODE").map(|m| m.to_ascii_lowercase()).unwrap_or_else(|_| "open".into()), default_refresh: default_refresh + Duration::from_secs(1), whitelist_refresh: whitelist_refresh + Duration::from_secs(1) }) } pub fn has_google_api_key(&self) -> bool { self.google_api_key.is_some() } pub fn port(&self) -> u16 { self.port } pub fn send_refresh_header(&self) -> bool { self.send_refresh_header } }