diff --git a/apps/gui/src-tauri/src/commands.rs b/apps/gui/src-tauri/src/commands.rs index 3ea7446..362ba7f 100644 --- a/apps/gui/src-tauri/src/commands.rs +++ b/apps/gui/src-tauri/src/commands.rs @@ -1,12 +1,12 @@ -use std::io::Error; +use std::{io::Error, path::Path}; use crate::{structs, utils, DATABASE}; use directories::{BaseDirs, UserDirs}; use entity::prelude::*; -use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, Set, ActiveModelTrait, ModelTrait}; -use serde::{Deserialize, Serialize}; -use minreq::post; use forge_lib::structs::v1::{unpack_v1_forgemod, ForgeModTypes}; +use minreq::post; +use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, ModelTrait, QueryFilter, Set}; +use serde::{Deserialize, Serialize}; static STEAM_PATH: &str = r"C:\Program Files (x86)\Steam\steamapps\common\Beat Saber"; static OCULUS_PATH: &str = @@ -14,17 +14,21 @@ static OCULUS_PATH: &str = #[tauri::command] pub async fn get_instances() -> Vec { - let db = DATABASE.get().await.clone(); + let db = DATABASE.get().await.clone(); - Instances::find().all(&db).await.unwrap().into_iter().map(|f| { - structs::Instance { + Instances::find() + .all(&db) + .await + .unwrap() + .into_iter() + .map(|f| structs::Instance { name: f.name, path: f.path, version: f.version, is_modded: f.is_modded, is_running: false, - } - }).collect() + }) + .collect() } #[tauri::command] @@ -73,6 +77,25 @@ pub async fn detect_instances(save: bool) -> Vec { if bsm_config["installation_folder"].as_str().is_none() { let bs_manager = documents_dir.join("BSManager").join("BSInstances"); + for entry in std::fs::read_dir(bs_manager).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + + if path.is_dir() { + instances.push(structs::Instance { + name: path.file_name().unwrap().to_str().unwrap().to_string(), + path: path.to_str().unwrap().to_string(), + version: utils::get_game_version(path.to_str().unwrap().to_string()), + is_modded: false, + is_running: false, + }); + } + } + } else { + let base_path = bsm_config["installation_folder"].as_str().unwrap(); // this is the base path for bs manager, not including BSManager + let mut bs_manager = Path::new(base_path).join("BSManager"); + bs_manager.push("BSInstances"); + for entry in std::fs::read_dir(bs_manager).unwrap() { let entry = entry.unwrap(); let path = entry.path(); @@ -102,7 +125,13 @@ pub async fn detect_instances(save: bool) -> Vec { ..Default::default() }; - if Instances::find().filter(entity::instances::Column::Name.eq(&f.name)).one(&db).await.unwrap().is_none() { + if Instances::find() + .filter(entity::instances::Column::Name.eq(&f.name)) + .one(&db) + .await + .unwrap() + .is_none() + { Instances::insert(am).exec(&db).await.unwrap(); } }); @@ -118,16 +147,21 @@ pub async fn add_instance(name: String) -> Result Result Result> { let db = DATABASE.get().await.clone(); - if let Some(i) = Instances::find().filter(entity::instances::Column::Name.eq(name)).one(&db).await? { + if let Some(i) = Instances::find() + .filter(entity::instances::Column::Name.eq(name)) + .one(&db) + .await? + { i.delete(&db).await?; return Ok(true); } @@ -148,12 +186,18 @@ pub async fn remove_instance(name: String) -> Result anyhow::Result<()> { +pub async fn install_mod( + instance_id: i32, + mod_id: String, + mod_version: String, + api_url: String, +) -> anyhow::Result<()> { let db = DATABASE.get().await.clone(); let instance = Instances::find_by_id(instance_id).one(&db).await?.unwrap(); let fm_res = post("https://staging-api.beatforge.net/graphql") - .with_body(format!("{{ + .with_body(format!( + "{{ mods {{ mod(id: \"{}\") {{ versions {{ @@ -161,10 +205,21 @@ pub async fn install_mod(instance_id: i32, mod_id: String, mod_version: String, }} }} }} - }}", mod_id)).send()?.json::()?.as_object().unwrap().get("data").unwrap().as_array().unwrap(); - + }}", + mod_id + )) + .send()? + .json::()? + .as_object() + .unwrap() + .get("data") + .unwrap() + .as_array() + .unwrap(); + let mut fm_bin = Vec::new(); - let forgemod = unpack_v1_forgemod(fm_bin.as_slice()).map_err(|e| anyhow::anyhow!("Failed to unpack forge mod: {}", e))?; + let forgemod = unpack_v1_forgemod(fm_bin.as_slice()) + .map_err(|e| anyhow::anyhow!("Failed to unpack forge mod: {}", e))?; match forgemod { ForgeModTypes::Mod(m) => { @@ -172,23 +227,30 @@ pub async fn install_mod(instance_id: i32, mod_id: String, mod_version: String, let artifact_name = m.manifest.inner.artifact.unwrap(); let artifact_name = artifact_name.file_name().unwrap().to_str().unwrap(); let includes = m.data.includes_data; - + for i in &includes { - if (i.dest.starts_with("..") || i.dest.starts_with("/")) && !i.dest.starts_with("../") { + if (i.dest.starts_with("..") || i.dest.starts_with("/")) + && !i.dest.starts_with("../") + { return Err(anyhow::anyhow!("Invalid include path: {}", i.dest)); } } - std::fs::write(format!("{}\\Plugins\\{}", instance.path, artifact_name), artifact_data)?; + std::fs::write( + format!("{}\\Plugins\\{}", instance.path, artifact_name), + artifact_data, + )?; includes.iter().for_each(|i| { std::fs::write(format!("{}\\{}", instance.path, i.dest), &*i.data).unwrap(); }) - }, + } _ => { - return Err(anyhow::anyhow!("TODO: other types of mods are not supported yet.")); + return Err(anyhow::anyhow!( + "TODO: other types of mods are not supported yet." + )); } } Ok(()) -} \ No newline at end of file +}