use anyhow::{Context, Result}; use serde::Deserialize; use std::fs; use std::fs::{create_dir_all, OpenOptions}; use std::io::Write; use std::process; use tracing::info; #[derive(Deserialize)] pub struct Config { pub player_bus: Option, pub username: String, pub password: String, pub api_key: String, pub api_secret: String } pub fn load_config() -> Result { let path = dirs::config_dir() .context("failed to get config directory")? .join("lastfmpris") .join("config.ini"); // create file if it doesnt exist and exit if !path.exists() { info!("configuration file doesn't exist, creating boilerplate"); // create underline paths and files if let Some(parent) = path.parent() { create_dir_all(parent) .context("failed to create config file folder(s)")?; } let mut file = OpenOptions::new() .write(true) .create(true) .open(&path) .context("failed to create config file")?; // write into the config file with the example configuration // we put inside the base working directory for the project file.write_all(include_str!("../config.example.ini").as_bytes()) .context("failed to write boilerplate config")?; info!("configuration boilerplate generation completed: see file: {}", path.display()); // success, exit process::exit(0) } let content = fs::read_to_string(path) .context("failed to read config content")?; let config: Config = serde_ini::from_str(&content) .context("failed to deserialize ini into a readable format")?; Ok(config) }