use std::{ fs::{create_dir_all, File}, io::{Read, Write}, path::Path, }; use serde::{Deserialize, Serialize}; use crate::{db::db_setup, error::MLE, Modloader, VersionLevel, check_game_versions}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Cfg { pub data: String, pub cache: String, pub versions: String, pub defaults: Defaults, pub apis: Apis, } #[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 { pub async fn init(path: Option) -> MLE { let configfile = match path.clone() { Some(p) => String::from(p), None => dirs::config_dir() .unwrap() .join("modlist") .join("config.toml") .to_string_lossy() .to_string(), }; let mut file = match File::open(&configfile) { Ok(file) => file, Err(err) => { if err.kind() == std::io::ErrorKind::NotFound && path.is_none() { create_config(&configfile)?; File::open(&configfile)? } else { return Err(err.into()); } } }; let mut content = String::new(); file.read_to_string(&mut content)?; let config = toml::from_str::(&content)?; //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); match File::open(&versionfile) { Ok(..) => (), Err(..) => { create_versions_dummy(&versionfile).await?; check_game_versions(&versionfile, true).await?; }, } Ok(config) } } fn create_config(path: &str) -> MLE<()> { print!("No config file found, create default"); //Force flush of stdout, else print! doesn't print instantly std::io::stdout().flush()?; let cache_dir = dirs::cache_dir() .unwrap() .join("modlist") .to_string_lossy() .to_string(); let default_cfg = Cfg { data: cache_dir.clone(), cache: format!("{}/cache", cache_dir), versions: cache_dir.clone(), defaults: Defaults { modloader: Modloader::Fabric, version: VersionLevel::Release }, apis: Apis { modrinth: String::from("https://api.modrinth.com/v2/"), }, }; create_dir_all(path.split("config.toml").collect::>()[0])?; let mut file = File::create(path)?; file.write_all(toml::to_string(&default_cfg)?.as_bytes())?; println!(" ✓"); Ok(()) } fn create_database(path: &str) -> MLE<()> { print!("No database found, create base"); //Force flush of stdout, else print! doesn't print instantly std::io::stdout().flush()?; File::create(path)?; db_setup(path)?; println!(" ✓"); Ok(()) } fn create_cache(path: &str) -> MLE<()> { print!("No cache direcory found, create one"); //Force flush of stdout, else print! doesn't print instantly std::io::stdout().flush()?; create_dir_all(path)?; println!(" ✓"); Ok(()) } async fn create_versions_dummy(path: &str) -> MLE<()> { print!("No version file found, create dummy"); //Force flush of stdout, else print! doesn't print instantly std::io::stdout().flush()?; File::create(path)?; println!(" ✓"); Ok(()) }