use std::{fs::File, io::{Read, Write}, path::PathBuf}; use zip::{write::FileOptions, ZipArchive, ZipWriter}; use crate::util; use super::{Profile, ProfilePaths}; impl Profile { fn find_template_json(archive: &mut ZipArchive) -> anyhow::Result { if let Ok(mut file) = archive.by_name("template.json") { let mut contents = Vec::new(); file.read_to_end(&mut contents)?; Ok(String::from_utf8(contents)?) } else { anyhow::bail!("invalid template: no template.json found") } } pub fn import(path: PathBuf) -> anyhow::Result<()> { let file = File::open(path)?; let mut archive = ZipArchive::new(file)?; match Self::find_template_json(&mut archive) { Ok(raw_p) => { let p = serde_json::from_str::(&raw_p)?; let dir = util::config_dir().join(format!("profile-{}-{}", &p.meta.game, &p.meta.name)); if dir.exists() { anyhow::bail!("profile {} already exists", &p.meta.name); } std::fs::create_dir(&dir)?; archive.extract(&dir)?; std::fs::remove_file(dir.join("template.json"))?; std::fs::write(dir.join("profile.json"), serde_json::to_string_pretty(&p.data)?)?; } Err(e) => { return Err(e); } } Ok(()) } pub fn export(&self, export_keychip: bool, extra_files: Vec, is_diagnostic: bool) -> anyhow::Result<()> { let mut prf = self.clone(); let dir = util::config_dir().join("exports"); if !dir.exists() { std::fs::create_dir(&dir)?; } let path = dir.join(format!("{}-{}-{}.zip", &self.meta.game, &self.meta.name, if is_diagnostic { "diagnostic" } else { "template" } )); { let sgt = &mut prf.data.sgt; sgt.target = PathBuf::new(); if sgt.amfs.is_absolute() { sgt.amfs = PathBuf::new(); } if sgt.option.is_absolute() { sgt.option = PathBuf::new(); } if sgt.appdata.is_absolute() { sgt.appdata = PathBuf::new(); } } { let network = &mut prf.data.network; if network.local_path.is_absolute() { network.local_path = PathBuf::new(); } if !export_keychip || is_diagnostic { network.keychip = String::new(); } } let file = File::create(&path)?; let mut zip = ZipWriter::new(file); let options: FileOptions<'_, ()> = FileOptions::default(); zip.start_file("template.json", options)?; zip.write_all(&serde_json::to_string_pretty(&prf)?.as_bytes())?; for file in extra_files { log::debug!("extra file: {file}"); zip.start_file(&file, options)?; zip.write_all(&std::fs::read(self.config_dir().join(file))?)?; } if is_diagnostic { let name = "mu3.exe.log"; let path = self.data_dir().join(name); if path.exists() { zip.start_file(name, options)?; zip.write_all(&std::fs::read(path)?)?; } let name = "chusanApp.exe.log"; let path = self.data_dir().join(name); if path.exists() { zip.start_file(name, options)?; zip.write_all(&std::fs::read(path)?)?; } let name = "amdaemon.exe.log"; let path = self.data_dir().join(name); if path.exists() { zip.start_file(name, options)?; zip.write_all(&std::fs::read(path)?)?; } } zip.finish()?; Ok(()) } }