use std::{collections::BTreeMap, fs::File, io::read_to_string, path::Path}; use rss::{Category, Cloud, Image, TextInput, extension::{Extension, dublincore::DublinCoreExtension, itunes::ITunesChannelExtension, syndication::SyndicationExtension}}; use serde::Deserialize; #[derive(Deserialize)] pub struct Config { pub subscriptions_path: Option, #[serde(default)] pub title: String, pub link: String, pub description: String, pub language: Option, pub copyright: Option, pub managing_editor: Option, pub webmaster: Option, #[serde(default)] pub categories: Vec, pub cloud: Option, pub ttl: Option, pub image: Option, pub text_input: Option, #[serde(default)] pub skip_hours: Vec, #[serde(default)] pub skip_days: Vec, #[serde(default)] pub extensions: BTreeMap>>, pub itunes_ext: Option, pub dublin_core_ext: Option, pub syndication_ext: Option, #[serde(default)] pub namespaces: BTreeMap, } pub fn default_config_file_locations() -> Vec { let mut default_config_file_locations = vec![ String::from("/etc/rss-aggregator/config.toml"), ]; let config_dir = dirs::config_dir() .and_then(|config_dir| config_dir.into_string().ok()); if let Some(config_dir) = config_dir { default_config_file_locations.push(format!("{config_dir}/rss-aggregator/config.toml")); }; default_config_file_locations } impl Config { pub fn parse_config_file_at_path(path: &str) -> anyhow::Result { let path = Path::new(path); let file = File::open(path)?; let contents = read_to_string(file)?; Ok(toml::from_str(&contents)?) } pub fn find_config() -> Option<(Config, String)> { for path in default_config_file_locations() { if let Ok(config) = Self::parse_config_file_at_path(&path) { return Some((config, path)); }; }; None } }