80 lines
2.8 KiB
Rust
80 lines
2.8 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use config::{Config, ConfigError, Environment};
|
|
use directories::ProjectDirs;
|
|
use serde::Deserialize;
|
|
use thiserror::Error;
|
|
use tracing::debug;
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum AppConfigError {
|
|
#[error("No valid home directory found.")]
|
|
HomePathError,
|
|
#[error("Configuration error.")]
|
|
ConfigError(#[from] ConfigError),
|
|
}
|
|
|
|
fn default_server_address() -> String {
|
|
String::from("[::1]:3000")
|
|
}
|
|
|
|
fn default_feeds() -> Vec<String> {
|
|
Vec::new()
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Deserialize)]
|
|
pub struct PenguinConfig {
|
|
#[serde(default = "default_server_address")]
|
|
pub server_address: String,
|
|
#[serde(default = "default_feeds")]
|
|
pub feeds: Vec<String>,
|
|
}
|
|
|
|
impl PenguinConfig {
|
|
/// Find the correct project directory for the respective operating system.
|
|
fn get_project_dirs() -> Result<ProjectDirs, AppConfigError> {
|
|
let project_dirs = ProjectDirs::from("ch", "vanwa", "findpenguins-feed")
|
|
.ok_or(AppConfigError::HomePathError)?;
|
|
|
|
Ok(project_dirs)
|
|
}
|
|
|
|
/// Find the correct configuration file for the respective operating system.
|
|
/// - linux: `$XDG_CONFIG_HOME/stray/config.toml` or `$HOME/.config/stray/config.toml`
|
|
/// - macOS: `$HOME/Library/Preferences/ch.fhnw.stray/config.toml`
|
|
/// - windows: `{FOLDERID_RoamingAppData}/stray/config/config.toml`
|
|
fn config_path() -> Result<PathBuf, AppConfigError> {
|
|
let project_dirs = Self::get_project_dirs()?;
|
|
let config_path = project_dirs.config_dir();
|
|
let config_file = config_path.join("config.toml");
|
|
|
|
Ok(config_file)
|
|
}
|
|
|
|
/// Read the server configuration.
|
|
/// See [config_path](struct.AppConfig.html#method.config_path) for the different configuration file paths.
|
|
/// Everything in the config file can be overridden at runtime by setting the respective ENV variables.
|
|
/// Use `__` (double underscore) as a separator between hierarchies.
|
|
/// For example `WOWEB__INITIAL_REMOTES="http://[::1]:3002,http://[::1]:3003"`
|
|
/// This is necessary for configuration keys to have single underscores.
|
|
pub fn read() -> Result<Self, AppConfigError> {
|
|
let mut config_builder = Config::builder();
|
|
if let Ok(config_path) = Self::config_path() {
|
|
debug!("trying config file at {:#?}...", config_path);
|
|
config_builder =
|
|
config_builder.add_source(config::File::from(config_path).required(false));
|
|
}
|
|
|
|
debug!("merging settings from environment variables...");
|
|
config_builder = config_builder.add_source(
|
|
Environment::with_prefix("findpenguins_feed")
|
|
.separator("__")
|
|
.list_separator(",")
|
|
.with_list_parse_key("feeds")
|
|
.try_parsing(true),
|
|
);
|
|
|
|
Ok(config_builder.build()?.try_deserialize()?)
|
|
}
|
|
}
|