use std::{ fs::{create_dir_all, File}, io::{Read, Write}, path::Path, }; use indicatif::{ProgressBar, ProgressStyle}; use serde::{Deserialize, Serialize}; use crate::{ check_game_versions, db::db_setup, error::MLE, Modloader, VersionLevel, }; #[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) => 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<()> { let p = ProgressBar::new(1); p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); p.set_message("Create default config"); 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, 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())?; p.finish_with_message(format!("Created default config ({})", path)); Ok(()) } fn create_database(path: &str) -> MLE<()> { let p = ProgressBar::new(1); p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); p.set_message("Create database"); File::create(path)?; db_setup(path)?; p.finish_with_message(format!("Created database ({})", path)); Ok(()) } fn create_cache(path: &str) -> MLE<()> { let p = ProgressBar::new(1); p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); p.set_message("Create cache"); create_dir_all(path)?; p.finish_with_message(format!("Created cache ({})", path)); Ok(()) } async fn create_versions_dummy(path: &str) -> MLE<()> { let p = ProgressBar::new(1); p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); p.set_message("Create version file"); File::create(path)?; p.finish_with_message(format!("Created version file ({})", path)); Ok(()) }