use std::fs::File; use asar::{AsarReader, AsarWriter}; use tokio::fs; use walkdir::WalkDir; pub struct RsiLauncherAsarData { pub asar_path: String, pub main_js_path: String, pub main_js_content: Vec, } impl RsiLauncherAsarData { pub async fn write_main_js(&self, content: Vec) -> anyhow::Result<()> { println!("[RsiLauncherAsarData] write_main_js"); let mut asar_writer = AsarWriter::new(); let asar_mem_file = fs::read(self.asar_path.clone()).await?; let asar = AsarReader::new(&asar_mem_file, None)?; let symlink_path = format!("{}.unpacked", self.asar_path); asar.files().iter().for_each(|v| { let (path, file) = v; let path_string = path.clone().into_os_string().into_string().unwrap(); if path_string == self.main_js_path { asar_writer.write_file(path, &content, true).unwrap(); } else { // check file exists in symlink_dir let file_path = format!("{}/{}", symlink_path, path_string); if std::fs::metadata(&file_path).is_ok() { println!("[RsiLauncherAsarData] skip file: {}", path_string); } else { println!("[RsiLauncherAsarData] write_file: {}", path_string); asar_writer.write_file(path, file.data(), true).unwrap(); } } }); // check if symlink_dir exists if fs::metadata(&symlink_path).await.is_ok() { // loop symlink_dir for entry in WalkDir::new(symlink_path.clone()) .follow_links(true) .into_iter() .filter_map(|e| e.ok()) { let f_path = entry.path(); if f_path.is_file() { let relative_path = f_path.strip_prefix(&symlink_path)?; let relative_path_str = relative_path.to_str().unwrap(); asar_writer.write_file(relative_path, &fs::read(f_path).await?, true, )?; // asar_writer.write_symlink(relative_path_str, f_path)?; println!( "[RsiLauncherAsarData] write symlink file: {} -> {}", relative_path_str, f_path.to_str().unwrap_or("??") ); } } } // rm old asar fs::remove_file(&self.asar_path).await?; // write new asar asar_writer.finalize(File::create(&self.asar_path)?)?; Ok(()) } } pub async fn get_rsi_launcher_asar_data(asar_path: &str) -> anyhow::Result { let asar_mem_file = fs::read(asar_path).await?; let asar = AsarReader::new(&asar_mem_file, None)?; let mut main_js_path = String::from(""); let mut main_js_content: Vec = Vec::new(); asar.files().iter().for_each(|v| { let (path, file) = v; let path_string = path.clone().into_os_string().into_string().unwrap(); if path_string.starts_with("app\\static\\js\\main.") && path_string.ends_with(".js") { main_js_path = path_string; main_js_content = file.data().to_vec(); } }); Ok(RsiLauncherAsarData { asar_path: asar_path.to_string(), main_js_path, main_js_content, }) }