diff --git a/src/main.rs b/src/main.rs index 93ac7c0..c76ddf6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,28 @@ +use std::unimplemented; + +use clap::{Args, Parser, Subcommand}; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +#[command(propagate_version = true)] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + Download(MapList), + Scan, + Replace, + Upload, +} + +#[derive(Args)] +struct MapList { + maps: Vec, +} + fn class_is_a(class: &str, superclass: &str) -> bool { if class==superclass { return true @@ -11,6 +36,19 @@ fn class_is_a(class: &str, superclass: &str) -> bool { return false } +//download + //download list of maps to maps/unprocessed +//scan (scripts) + //iter maps/unprocessed + //passing moves to maps/verified + //failing moves to maps/purgatory +//replace (edits & deletions) + //iter maps/purgatory + //replace scripts and put in maps/unprocessed +//upload + //iter maps/verified + //interactively print DisplayName/Creator and ask for target upload ids + fn get_scripts(dom:rbx_dom_weak::WeakDom) -> Vec{ let mut scripts = std::vec::Vec::::new(); @@ -23,19 +61,33 @@ fn get_scripts(dom:rbx_dom_weak::WeakDom) -> Vec{ scripts } -fn main() -> Result<(), Box> { - // Using buffered I/O is recommended with rbx_binary - let input = std::io::BufReader::new(std::fs::File::open("map.rbxm")?); - - let dom = rbx_binary::from_reader(input)?; - +fn download(map_list: Vec) -> Result<(), Box>{ + unimplemented!() +} +fn scan() -> Result<(), Box>{ + let mut id = 0u32; + match std::fs::read_to_string("id"){ + Ok(id_file)=>id=id_file.parse::()?, + Err(e) => match e.kind() { + std::io::ErrorKind::NotFound => println!("id file does not exist: starting from 0"),//continue on, implicitly take on id=0, write the id file at the end + _ => return Err(e)?, + } + } //Construct allowed scripts - let mut allowed = std::collections::HashSet::::new(); - for entry in std::fs::read_dir("allowed")? { - allowed.insert(std::fs::read_to_string(entry?.path())?); + let mut allowed_set = std::collections::HashSet::::new(); + for entry in std::fs::read_dir("scripts/allowed")? { + allowed_set.insert(std::fs::read_to_string(entry?.path())?); + } + let mut blocked = std::collections::HashSet::::new(); + for entry in std::fs::read_dir("scripts/blocked")? { + blocked.insert(std::fs::read_to_string(entry?.path())?); } + for entry in std::fs::read_dir("maps/unprocessed")? { + let file_thing=entry?; + let input = std::io::BufReader::new(std::fs::File::open(file_thing.path())?); + let dom = rbx_binary::from_reader(input)?; let scripts = get_scripts(dom); @@ -43,32 +95,103 @@ fn main() -> Result<(), Box> { let mut any_failed=false; for script in scripts.iter() { if let Some(rbx_dom_weak::types::Variant::String(s)) = script.properties.get("Source") { - if allowed.contains(s) { + if allowed_set.contains(s) { println!("pass"); + continue; }else{ println!("fail"); any_failed=true; - std::fs::write(format!("blocked/{}.lua",i),s)?; + if !blocked.contains(s) { + blocked.insert(s.clone());//all fixed! just clone! + std::fs::write(format!("scripts/blocked/{}.lua",id),s)?; + id+=1; + } } }else{ println!("failed to get source"); any_failed=true; } + } + if any_failed { + println!("One or more scripts are not allowed."); }else{ - println!("failed to deref script"); - any_failed=true; + let mut dest=std::path::PathBuf::from("maps/processed"); + dest.set_file_name(file_thing.file_name()); + dest.set_extension("rbxl");//extension is always rbxl even if source file is extensionless + std::fs::rename(file_thing.path(), dest)?; } } - if any_failed { - println!("One or more scripts are not allowed."); - return Ok(())//everything is not ok but idk how to return an error LMAO + std::fs::write("id",id.to_string())?; + Ok(()) +} +fn replace() -> Result<(), Box>{ + //Construct allowed scripts + let mut allowed_map = std::collections::HashMap::::new(); + for entry in std::fs::read_dir("scripts/allowed")? { + let entry=entry?; + allowed_map.insert(entry.file_name().to_str().unwrap().parse::()?,std::fs::read_to_string(entry.path())?); } - println!("All scripts passed!"); + let mut replace = std::collections::HashMap::::new(); + for entry in std::fs::read_dir("scripts/replace")? { + let entry=entry?; + replace.insert(std::fs::read_to_string(entry.path())?,entry.file_name().to_str().unwrap().parse::()?); + } + + for entry in std::fs::read_dir("maps/purgatory")? { + let file_thing=entry?; + let input = std::io::BufReader::new(std::fs::File::open(file_thing.path())?); + + let dom = rbx_binary::from_reader(input)?; + + let mut write_dom = rbx_dom_weak::WeakDom::new(rbx_dom_weak::InstanceBuilder::empty()); + dom.clone_into_external(dom.root_ref(), &mut write_dom); + + let scripts = get_scripts(dom); + + //check scribb + let mut any_failed=false; + for script in scripts.iter() { + if let Some(rbx_dom_weak::types::Variant::String(source)) = script.properties.get("Source") { + if let (Some(replace_id),Some(replace_script))=(replace.get(source),write_dom.get_by_ref_mut(script.referent())) { + println!("replace {}",replace_id); + //replace the source + if let Some(replace_source)=allowed_map.get(replace_id){ + replace_script.properties.insert("Source".to_string(), rbx_dom_weak::types::Variant::String(replace_source.clone())); + }else{ + println!("failed to get replacement source {}",replace_id); + any_failed=true; + } + } + } + } + if any_failed { + println!("One or more scripts failed to replace."); + }else{ + let mut dest=std::path::PathBuf::from("maps/unprocessed"); + dest.set_file_name(file_thing.file_name()); + dest.set_extension("rbxl");//extension is always rbxl even if source file is extensionless + let output = std::io::BufWriter::new(std::fs::File::open(dest)?); + rbx_binary::to_writer(output, &write_dom, &[write_dom.root_ref()])?; + } + } + Ok(()) +} +fn upload() -> Result<(), Box>{ // std::process::Command::new("rbxcompiler") // .arg("--compile=false") // .arg("--group=6980477") // .arg("--asset=5692139100") // .arg("--input=map.rbxm") // .spawn()?; - Ok(()) + unimplemented!() +} + +fn main() -> Result<(), Box> { + let cli = Cli::parse(); + match cli.command { + Commands::Download(map_list)=>download(map_list.maps), + Commands::Scan=>scan(), + Commands::Replace=>replace(), + Commands::Upload=>upload(), + } }