use figment::{
Figment,
providers::{Env, Format, Serialized, Toml},
};
use serde::{Deserialize, Serialize};
use crate::error::{LarkWebhookError, Result};
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
pub struct LarkWebhookSettings {
pub webhook_url: Option<String>,
pub webhook_secret: Option<String>,
}
impl LarkWebhookSettings {
pub fn load(
toml_file: Option<&str>,
webhook_url: Option<String>,
webhook_secret: Option<String>,
) -> Result<Self> {
let path = toml_file.unwrap_or("lark_webhook.toml");
let mut settings: LarkWebhookSettings =
Figment::from(Serialized::defaults(LarkWebhookSettings::default()))
.merge(Toml::file(path))
.merge(Env::prefixed("LARK_"))
.extract()
.map_err(|e| LarkWebhookError::Config(e.to_string()))?;
if let Some(url) = webhook_url {
settings.webhook_url = Some(url);
}
if let Some(secret) = webhook_secret {
settings.webhook_secret = Some(secret);
}
Ok(settings)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Mutex;
static ENV_MUTEX: Mutex<()> = Mutex::new(());
#[test]
fn test_defaults_are_none() {
let _guard = ENV_MUTEX.lock().unwrap();
let s = LarkWebhookSettings::load(Some("nonexistent_xyz.toml"), None, None).unwrap();
assert!(s.webhook_url.is_none());
assert!(s.webhook_secret.is_none());
}
#[test]
fn test_direct_params_override() {
let _guard = ENV_MUTEX.lock().unwrap();
let s = LarkWebhookSettings::load(
None,
Some("https://direct.url".to_owned()),
Some("direct_secret".to_owned()),
)
.unwrap();
assert_eq!(s.webhook_url.as_deref(), Some("https://direct.url"));
assert_eq!(s.webhook_secret.as_deref(), Some("direct_secret"));
}
#[test]
fn test_toml_file_loading() {
let _guard = ENV_MUTEX.lock().unwrap();
use std::io::Write;
let mut f = tempfile::NamedTempFile::new().unwrap();
write!(
f,
"webhook_url = \"https://toml.url\"\nwebhook_secret = \"toml_secret\"\n"
)
.unwrap();
let path = f.path().to_str().unwrap().to_owned();
let s = LarkWebhookSettings::load(Some(&path), None, None).unwrap();
assert_eq!(s.webhook_url.as_deref(), Some("https://toml.url"));
assert_eq!(s.webhook_secret.as_deref(), Some("toml_secret"));
}
#[test]
fn test_env_var_loading() {
let _guard = ENV_MUTEX.lock().unwrap();
unsafe {
std::env::set_var("LARK_WEBHOOK_URL", "https://env.url");
std::env::set_var("LARK_WEBHOOK_SECRET", "env_secret");
}
let result = LarkWebhookSettings::load(Some("nonexistent_xyz.toml"), None, None);
unsafe {
std::env::remove_var("LARK_WEBHOOK_URL");
std::env::remove_var("LARK_WEBHOOK_SECRET");
}
let s = result.unwrap();
assert_eq!(s.webhook_url.as_deref(), Some("https://env.url"));
assert_eq!(s.webhook_secret.as_deref(), Some("env_secret"));
}
}