use std::{ fs::{create_dir_all, File}, io::Write, path::Path, }; use serde::{Deserialize, Serialize}; use crate::{ data::{ gameversion::{check_game_versions, VersionLevel}, modloader::Modloader, }, db::setup, errors::{Error, MLE}, }; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Cfg { pub data: String, pub cache: String, pub versions: String, pub defaults: Defaults, pub apis: Apis, } impl Default for Cfg { fn default() -> Self { let cache_dir = dirs::cache_dir() .unwrap() .join("modlist") .to_string_lossy() .to_string(); Self { data: cache_dir.clone(), cache: format!("{cache_dir}/cache"), versions: cache_dir, defaults: Defaults { modloader: Modloader::Fabric, version: VersionLevel::Release, }, apis: Apis { modrinth: String::from("https://api.modrinth.com/v2/"), }, } } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Apis { pub modrinth: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Defaults { pub modloader: Modloader, pub version: VersionLevel, } impl Cfg { /// # Errors pub async fn init(path: Option) -> MLE { let configfile = if let Some(cf) = path.clone() { cf } else { let Some(config_dir) = dirs::config_dir() else { return Err(Error::SysDirNotFound("config".to_string())); }; config_dir .join("modlist") .join("config.toml") .to_string_lossy() .to_string() }; if let Some(err) = File::open(&configfile).err() { if err.kind() == std::io::ErrorKind::NotFound && path.is_none() { create_config(&configfile)?; } else { return Err(err.into()); }; }; let config: Cfg = config::Config::builder() .add_source(config::File::with_name(&configfile).required(false)) .add_source( config::Environment::with_prefix("MODLIST").separator("_"), ) .build()? .try_deserialize()?; //Check cache if !Path::new(&config.cache).exists() { create_cache(&config.cache)?; }; //Check database let datafile = format!("{}/data.db", config.data); match File::open(&datafile) { Ok(..) => (), Err(..) => create_database(&datafile)?, }; //Check versions let versionfile = format!("{}/versions.json", config.versions); if File::open(&versionfile).is_err() { create_versions_dummy(&versionfile)?; check_game_versions(&versionfile, true).await?; } Ok(config) } } fn create_config(path: &str) -> MLE<()> { create_dir_all(path.split("config.toml").collect::>()[0])?; let mut file = File::create(path)?; file.write_all(toml::to_string(&Cfg::default())?.as_bytes())?; println!("Created default config ({path})"); Ok(()) } fn create_database(path: &str) -> MLE<()> { File::create(path)?; setup(path)?; println!("Created database ({path})"); Ok(()) } fn create_cache(path: &str) -> MLE<()> { create_dir_all(path)?; println!("Created cache ({path})"); Ok(()) } fn create_versions_dummy(path: &str) -> MLE<()> { File::create(path)?; println!("Created version file ({path})"); Ok(()) }