#![allow(dead_code)]
use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub user: UserConfig,
pub database: DatabaseConfig,
#[serde(default)]
pub server: ServerConfig,
#[serde(default)]
pub tts: TtsConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserConfig {
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseConfig {
pub url: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
pub port: u16,
pub bind: String,
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
port: 7878,
bind: "127.0.0.1".into(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct TtsConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default)]
pub voice_id: Option<String>,
#[serde(default)]
pub api_key: Option<String>,
#[serde(default = "default_true")]
pub daily_greeting: bool,
#[serde(default = "default_quiet_hours")]
pub quiet_hours: Option<String>,
#[serde(default = "default_true")]
pub auto_speak_advice: bool,
}
fn default_true() -> bool {
true
}
fn default_quiet_hours() -> Option<String> {
Some("21:00-09:00".into())
}
impl Config {
pub fn load(path: &Path) -> Result<Self> {
if !path.exists() {
return Err(anyhow!(
"Asurada config not found at {}.\n먼저 `asurada init` 을 실행하세요.",
path.display()
));
}
let text = fs::read_to_string(path).with_context(|| format!("read {}", path.display()))?;
let cfg: Config =
toml::from_str(&text).with_context(|| format!("parse {}", path.display()))?;
if cfg.user.id.trim().is_empty() {
return Err(anyhow!("config.user.id 비어있음 — `asurada init` 재실행"));
}
if cfg.database.url.trim().is_empty() {
return Err(anyhow!(
"config.database.url 미설정 — `asurada init` 으로 설정"
));
}
Ok(cfg)
}
pub fn save(&self, path: &Path) -> Result<()> {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).ok();
}
let text = toml::to_string_pretty(self)?;
fs::write(path, text).with_context(|| format!("write {}", path.display()))?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let perms = fs::Permissions::from_mode(0o600);
let _ = fs::set_permissions(path, perms);
}
Ok(())
}
pub fn fresh(database_url: String) -> Self {
Self {
user: UserConfig {
id: uuid::Uuid::new_v4().to_string(),
},
database: DatabaseConfig { url: database_url },
server: ServerConfig::default(),
tts: TtsConfig::default(),
}
}
}