initial commit

This commit is contained in:
2025-02-12 22:13:31 +01:00
commit 047b2e9f4a
52 changed files with 8552 additions and 0 deletions

182
rust/src/cmd.rs Normal file
View File

@ -0,0 +1,182 @@
use log;
use std::fs::{self, File};
use tokio::io::AsyncWriteExt;
use tokio::sync::Mutex;
use crate::pkg_remote;
use crate::pkg_local;
use crate::util;
use crate::{types, AppData};
use crate::types::{local, Package};
use tauri::State;
#[tauri::command]
pub async fn startline(
state: State<'_, Mutex<AppData>>,
) -> Result<Option<local::Profile>, ()> {
log::debug!("invoke: startline");
let appd = state.lock().await;
Ok(appd.profile.clone())
}
#[tauri::command]
pub async fn download_package(pkg: Package) {
log::debug!("invoke: download_package");
use futures::StreamExt;
let zip_path = util::get_dirs().cache_dir().join(format!(
"{}-{}-{}.zip",
pkg.namespace, pkg.name, pkg.version
));
if !zip_path.exists() {
// let zip_path_part = zip_path.add_extension("part");
let mut zip_path_part = zip_path.clone();
zip_path_part.set_extension("zip.part");
let mut cache_file_w = tokio::fs::File::create(&zip_path_part).await.unwrap();
let mut byte_stream = reqwest::get(&pkg.download_url)
.await
.unwrap()
.bytes_stream();
log::info!("downloading: {}", pkg.download_url);
while let Some(item) = byte_stream.next().await {
let i = item.unwrap();
cache_file_w.write_all(&mut i.as_ref()).await.unwrap();
}
cache_file_w.sync_all().await.unwrap();
tokio::fs::rename(&zip_path_part, &zip_path).await.unwrap();
}
let cache_file_r = File::open(&zip_path).unwrap();
let mut archive = zip::ZipArchive::new(cache_file_r).unwrap();
delete_package(pkg.namespace.clone(), pkg.name.clone())
.await
.unwrap();
let path = util::get_dirs()
.data_dir()
.join("pkg")
.join(format!("{}-{}", pkg.namespace, pkg.name));
fs::create_dir(&path).unwrap();
archive.extract(path).unwrap();
}
#[tauri::command]
pub async fn delete_package(namespace: String, name: String) -> Result<(), String> {
log::debug!("invoke: download_package");
let path = util::get_dirs()
.data_dir()
.join("pkg")
.join(format!("{}-{}", namespace, name));
if path.exists() && path.join("manifest.json").exists() {
log::debug!("rm -r'ing {}", path.to_string_lossy());
return tokio::fs::remove_dir_all(&path)
.await
.map_err(|e| e.to_string());
}
Ok(())
}
#[tauri::command]
pub async fn reload_packages(state: State<'_, tokio::sync::Mutex<AppData>>) -> Result<(), ()> {
log::debug!("invoke: reload_packages");
let mut appd = state.lock().await;
// todo: this should only fetch new things
appd.mods_local = pkg_local::walk_packages(false).await;
Ok(())
}
#[tauri::command]
pub async fn get_packages(state: State<'_, Mutex<AppData>>) -> Result<Vec<Package>, ()> {
log::debug!("invoke: get_packages");
let appd = state.lock().await;
log::debug!("Returning {} packages", appd.mods_local.len());
Ok(appd.mods_local.clone())
}
#[tauri::command]
pub async fn get_listings(state: State<'_, Mutex<AppData>>) -> Result<Vec<Package>, String> {
log::debug!("invoke: get_listings");
let should_fetch;
{
let appd = state.lock().await;
should_fetch = appd.mods_store.len() == 0;
}
if should_fetch {
let listings = pkg_remote::fetch_listings().await?;
let mut appd = state.lock().await;
appd.mods_store = listings;
Ok(appd.mods_store.clone())
} else {
let appd = state.lock().await;
Ok(appd.mods_store.clone())
}
}
#[tauri::command]
pub async fn get_current_profile(
state: State<'_, Mutex<AppData>>,
) -> Result<Option<local::Profile>, ()> {
log::debug!("invoke: get_current_profile");
let appd = state.lock().await;
Ok(appd.profile.clone())
}
#[tauri::command]
pub async fn save_profile(
state: State<'_, Mutex<AppData>>
) -> Result<(), ()> {
log::debug!("invoke: save_profile");
let appd = state.lock().await;
if let Some(profile) = &appd.profile {
let path = util::get_dirs().config_dir().join("profile-ongeki-default.json");
let s = serde_json::to_string_pretty(profile).unwrap();
tokio::fs::write(&path, s).await.unwrap();
log::info!("Written to {}", path.to_string_lossy());
} else {
log::error!("No profile to save");
}
Ok(())
}
#[tauri::command]
pub async fn init_profile(
state: State<'_, Mutex<AppData>>,
path: String
) -> Result<local::Profile, ()> {
log::debug!("invoke: init_profile");
let new_profile = local::Profile {
game: types::misc::Game::Ongeki,
path: path,
name: "ongeki-default".to_owned(),
mods: [].to_vec()
};
{
let mut appd = state.lock().await;
appd.profile = Some(new_profile.clone());
}
save_profile(state).await.unwrap();
Ok(new_profile)
}