|
| 1 | +use colored::*; |
| 2 | +use crate::utils::{handle_cybersecurity, handle_gaming, run_command_with_progress}; |
| 3 | +use crate::UnpackCommands; |
| 4 | +use crate::SystemCommands; |
| 5 | +use crate::RunCommands; |
| 6 | +use std::io::{self, BufRead}; |
| 7 | +use std::fs::{self, File}; |
| 8 | +use std::path::Path; |
| 9 | +use std::process::{Command, Stdio}; |
| 10 | +use chrono::{DateTime, Utc, Duration as ChronoDuration}; |
| 11 | +use std::env; |
1 | 12 |
|
| 13 | +pub fn handle_unpack(unpack_command: UnpackCommands) { |
| 14 | + match unpack_command { |
| 15 | + UnpackCommands::AddOns => { |
| 16 | + println!("{}", "========== Installing Add-Ons ==========".cyan().bold().on_black()); |
| 17 | + run_command_with_progress("flatpak", vec!["remote-add", "--if-not-exists", "flathub", "https://dl.flathub.org/repo/flathub.flatpakrepo"], "Adding flathub repo"); |
| 18 | + run_command_with_progress("sudo", vec!["apt", "install", "-y", "wine", "winetricks"], "Installing Wine"); |
| 19 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "io.github.dvlv.boxbuddyrs"], "Installing BoxBuddy"); |
| 20 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "it.mijorus.winezgui"], "Installing Winezgui"); |
| 21 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "it.mijorus.gearlever"], "Installing Gearlever"); |
| 22 | + println!("{}", "========== Install Add-Ons Complete ==========".green().bold().on_black()); |
| 23 | + } |
| 24 | + UnpackCommands::GS => { |
| 25 | + handle_gaming(); |
| 26 | + handle_cybersecurity(); |
| 27 | + } |
| 28 | + UnpackCommands::Devtools => { |
| 29 | + println!("{}", "========== Installing Atom ==========".cyan().bold().on_black()); |
| 30 | + run_command_with_progress("flatpak", vec!["remote-add", "--if-not-exists", "flathub", "https://dl.flathub.org/repo/flathub.flatpakrepo"], "Adding flathub repo"); |
| 31 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "io.atom.Atom"], "Installing Atom"); |
| 32 | + println!("{}", "========== Install Dev Tools Complete ==========".green().bold().on_black()); |
| 33 | + } |
| 34 | + UnpackCommands::Emulators => { |
| 35 | + println!("{}", "========== Installing Emulators ==========".cyan().bold().on_black()); |
| 36 | + run_command_with_progress("flatpak", vec!["remote-add", "--if-not-exists", "flathub", "https://dl.flathub.org/repo/flathub.flatpakrepo"], "Adding flathub repo"); |
| 37 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "org.shadps4.shadPS4"], "Installing PlayStation Emulator"); |
| 38 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "io.github.ryubing.Ryujinx"], "Installing Nintendo Emulator"); |
| 39 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "com.dosbox_x.DOSBox-X"], "Installing DOSBox"); |
| 40 | + // Removed snap install for rpcs3-emu |
| 41 | + println!("{}", "========== Hacker-Unpack-Emulators Complete ==========".green().bold().on_black()); |
| 42 | + } |
| 43 | + UnpackCommands::Cybersecurity => { |
| 44 | + handle_cybersecurity(); |
| 45 | + } |
| 46 | + UnpackCommands::Select => { |
| 47 | + println!("{}", "========== Interactive Package Selection ==========".yellow().bold().on_black()); |
| 48 | + println!("{}", "Select packages to install (enter numbers separated by commas, e.g., 1,3,5):".cyan().bold()); |
| 49 | + println!("{}", "1. Add-Ons (Wine, BoxBuddy, etc.)".white().bold()); |
| 50 | + println!("{}", "2. Gaming Tools (Steam, Lutris, etc.)".white().bold()); |
| 51 | + println!("{}", "3. Cybersecurity Tools (nmap, wireshark, etc.)".white().bold()); |
| 52 | + println!("{}", "4. Devtools (Atom)".white().bold()); |
| 53 | + println!("{}", "5. Emulators (PlayStation, Nintendo, etc.)".white().bold()); |
| 54 | + println!("{}", "6. Hacker Mode (gamescope)".white().bold()); |
| 55 | + println!("{}", "7. Gaming No Roblox".white().bold()); |
| 56 | + let mut input = String::new(); |
| 57 | + io::stdin().read_line(&mut input).expect("Failed to read line"); |
| 58 | + let selections: Vec<u32> = input.trim().split(',').filter_map(|s| s.parse().ok()).collect(); |
| 59 | + for &sel in &selections { |
| 60 | + match sel { |
| 61 | + 1 => handle_unpack(UnpackCommands::AddOns), |
| 62 | + 2 => handle_unpack(UnpackCommands::Gaming), |
| 63 | + 3 => handle_unpack(UnpackCommands::Cybersecurity), |
| 64 | + 4 => handle_unpack(UnpackCommands::Devtools), |
| 65 | + 5 => handle_unpack(UnpackCommands::Emulators), |
| 66 | + 6 => handle_unpack(UnpackCommands::HackerMode), |
| 67 | + 7 => handle_unpack(UnpackCommands::Noroblox), |
| 68 | + _ => println!("{}", "Invalid selection!".red().bold()), |
| 69 | + } |
| 70 | + } |
| 71 | + println!("{}", "========== Selection Complete ==========".green().bold().on_black()); |
| 72 | + } |
| 73 | + UnpackCommands::Gaming => { |
| 74 | + handle_gaming(); |
| 75 | + } |
| 76 | + UnpackCommands::Noroblox => { |
| 77 | + println!("{}", "========== Installing Gaming Tools (No Roblox) ==========".cyan().bold().on_black()); |
| 78 | + run_command_with_progress("flatpak", vec!["remote-add", "--if-not-exists", "flathub", "https://dl.flathub.org/repo/flathub.flatpakrepo"], "Adding flathub repo"); |
| 79 | + run_command_with_progress("sudo", vec!["apt", "install", "-y", "obs-studio", "lutris"], "Installing OBS Studio and Lutris"); |
| 80 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "com.valvesoftware.Steam"], "Installing Steam"); |
| 81 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "io.github.giantpinkrobots.varia"], "Installing Pika Torrent"); |
| 82 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "net.davidotek.pupgui2"], "Installing ProtonUp-Qt"); |
| 83 | + run_command_with_progress("flatpak", vec!["install", "-y", "flathub", "com.heroicgameslauncher.hgl", "protontricks", "com.discordapp.Discord"], "Installing Heroic Games Launcher, Protontricks, and Discord"); |
| 84 | + println!("{}", "========== Hacker-Unpack-Gaming-NoRoblox Complete ==========".green().bold().on_black()); |
| 85 | + } |
| 86 | + UnpackCommands::HackerMode => { |
| 87 | + println!("{}", "========== Installing Hacker Mode ==========".cyan().bold().on_black()); |
| 88 | + run_command_with_progress("sudo", vec!["apt", "install", "-y", "gamescope"], "Installing gamescope"); |
| 89 | + println!("{}", "========== Hacker Mode Install Complete ==========".green().bold().on_black()); |
| 90 | + } |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +pub fn handle_system(system_command: SystemCommands) { |
| 95 | + match system_command { |
| 96 | + SystemCommands::Logs => { |
| 97 | + println!("{}", "========== System Logs ==========".cyan().bold().on_black()); |
| 98 | + run_command_with_progress("sudo", vec!["journalctl", "-xe"], "Displaying system logs"); |
| 99 | + } |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +pub fn handle_run(cmd: RunCommands) { |
| 104 | + // All runs with chattr -i if immutable |
| 105 | + make_mutable(); |
| 106 | + match cmd { |
| 107 | + RunCommands::HackerosCockpit => run_command_with_progress("sudo", vec!["python3", "/usr/share/HackerOS/Scripts/HackerOS-Apps/HackerOS-Cockpit/HackerOS-Cockpit.py"], "Running HackerOS Cockpit"), |
| 108 | + RunCommands::SwitchToOtherSession => run_command_with_progress("sudo", vec!["/usr/share/HackerOS/Scripts/Bin/Switch_To_Other_Session.sh"], "Switching to other session"), |
| 109 | + RunCommands::UpdateSystem => run_command_with_progress("sudo", vec!["/usr/share/HackerOS/Scripts/Bin/update-system.sh"], "Updating system"), |
| 110 | + RunCommands::CheckUpdates => run_command_with_progress("sudo", vec!["/usr/share/HackerOS/Scripts/Bin/check_updates_notify.sh"], "Checking for updates"), |
| 111 | + RunCommands::Steam => run_command_with_progress("bash", vec!["/usr/share/HackerOS/Scripts/Steam/HackerOS-Steam.sh"], "Launching Steam"), |
| 112 | + RunCommands::HackerLauncher => run_command_with_progress("bash", vec!["/usr/share/HackerOS/Scripts/HackerOS-Apps/Hacker_Launcher"], "Launching HackerOS Launcher"), |
| 113 | + RunCommands::HackerosGameMode => run_command_with_progress("", vec!["/usr/share/HackerOS/Scripts/HackerOS-Apps/HackerOS-Game-Mode.AppImage"], "Running HackerOS Game Mode"), |
| 114 | + RunCommands::UpdateHackeros => run_command_with_progress("sudo", vec!["/usr/share/HackerOS/Scripts/Bin/update-hackeros.sh"], "Updating HackerOS"), |
| 115 | + } |
| 116 | + make_immutable(); |
| 117 | +} |
| 118 | + |
| 119 | +pub fn handle_immutable() { |
| 120 | + println!("{}", "Making system immutable...".cyan().bold()); |
| 121 | + let paths = vec!["/bin", "/sbin", "/usr", "/etc", "/lib", "/lib64", "/var"]; |
| 122 | + for path in paths { |
| 123 | + run_command_with_progress("sudo", vec!["chattr", "+i", "-R", path], &format!("Making {} immutable", path)); |
| 124 | + } |
| 125 | + println!("{}", "System is now immutable.".green().bold()); |
| 126 | +} |
| 127 | + |
| 128 | +pub fn handle_runtime(script: &str) { |
| 129 | + if !is_safe_script(script) { |
| 130 | + println!("{}", "Script contains unsafe commands! Aborting.".red().bold()); |
| 131 | + return; |
| 132 | + } |
| 133 | + make_mutable(); |
| 134 | + if script.ends_with(".hacker") { |
| 135 | + // Assume hackerc is the compiler/runner |
| 136 | + run_command_with_progress("hackerc", vec![script], "Running .hacker script"); |
| 137 | + } else { |
| 138 | + run_command_with_progress("bash", vec![script], "Running script"); |
| 139 | + } |
| 140 | + make_immutable(); |
| 141 | +} |
| 142 | + |
| 143 | +fn is_safe_script(script_path: &str) -> bool { |
| 144 | + if let Ok(file) = File::open(script_path) { |
| 145 | + let reader = io::BufReader::new(file); |
| 146 | + let dangerous_commands = vec!["rm -rf /", "dd if=/dev/zero", "mkfs", ":(){ :|:& };:"]; |
| 147 | + for line in reader.lines() { |
| 148 | + if let Ok(line) = line { |
| 149 | + for cmd in &dangerous_commands { |
| 150 | + if line.contains(cmd) { |
| 151 | + return false; |
| 152 | + } |
| 153 | + } |
| 154 | + } |
| 155 | + } |
| 156 | + true |
| 157 | + } else { |
| 158 | + false |
| 159 | + } |
| 160 | +} |
| 161 | + |
| 162 | +fn make_mutable() { |
| 163 | + let paths = vec!["/bin", "/sbin", "/usr", "/etc", "/lib", "/lib64", "/var"]; |
| 164 | + for path in paths { |
| 165 | + run_command_with_progress("sudo", vec!["chattr", "-i", "-R", path], &format!("Making {} mutable", path)); |
| 166 | + } |
| 167 | +} |
| 168 | + |
| 169 | +fn make_immutable() { |
| 170 | + let paths = vec!["/bin", "/sbin", "/usr", "/etc", "/lib", "/lib64", "/var"]; |
| 171 | + for path in paths { |
| 172 | + run_command_with_progress("sudo", vec!["chattr", "+i", "-R", path], &format!("Making {} immutable", path)); |
| 173 | + } |
| 174 | +} |
| 175 | + |
| 176 | +pub fn handle_install(package: &str) { |
| 177 | + println!("{}", "Installing package in snapshot...".cyan().bold()); |
| 178 | + let snapshot_dir = "/var/cache/hacker/"; |
| 179 | + fs::create_dir_all(snapshot_dir).expect("Failed to create snapshot dir"); |
| 180 | + let timestamp = Utc::now().format("%Y%m%d%H%M%S").to_string(); |
| 181 | + let new_snapshot = format!("{}/snapshot-{}", snapshot_dir, timestamp); |
| 182 | + run_command_with_progress("sudo", vec!["btrfs", "subvolume", "snapshot", "/", &new_snapshot], "Creating new snapshot"); |
| 183 | + // Chroot and install |
| 184 | + run_command_with_progress("sudo", vec!["chroot", &new_snapshot, "/usr/share/HackerOS/apt", "install", "-y", package], "Installing package in snapshot"); |
| 185 | + // Assume bootloader update or set as next boot |
| 186 | + run_command_with_progress("sudo", vec!["btrfs", "subvolume", "set-default", &new_snapshot], "Setting new snapshot as default"); |
| 187 | + println!("{}", "Package installed in snapshot. Reboot to apply.".green().bold()); |
| 188 | + // Save current snapshot |
| 189 | + let current_snapshot = format!("{}/current-{}", snapshot_dir, timestamp); |
| 190 | + run_command_with_progress("sudo", vec!["btrfs", "subvolume", "snapshot", "/", ¤t_snapshot], "Saving current snapshot"); |
| 191 | +} |
| 192 | + |
| 193 | +pub fn handle_remove(package: &str) { |
| 194 | + println!("{}", "Removing package in snapshot...".cyan().bold()); |
| 195 | + let snapshot_dir = "/var/cache/hacker/"; |
| 196 | + fs::create_dir_all(snapshot_dir).expect("Failed to create snapshot dir"); |
| 197 | + let timestamp = Utc::now().format("%Y%m%d%H%M%S").to_string(); |
| 198 | + let new_snapshot = format!("{}/snapshot-{}", snapshot_dir, timestamp); |
| 199 | + run_command_with_progress("sudo", vec!["btrfs", "subvolume", "snapshot", "/", &new_snapshot], "Creating new snapshot"); |
| 200 | + // Chroot and remove |
| 201 | + run_command_with_progress("sudo", vec!["chroot", &new_snapshot, "/usr/share/HackerOS/apt", "remove", "-y", package], "Removing package in snapshot"); |
| 202 | + run_command_with_progress("sudo", vec!["btrfs", "subvolume", "set-default", &new_snapshot], "Setting new snapshot as default"); |
| 203 | + println!("{}", "Package removed in snapshot. Reboot to apply.".green().bold()); |
| 204 | + let current_snapshot = format!("{}/current-{}", snapshot_dir, timestamp); |
| 205 | + run_command_with_progress("sudo", vec!["btrfs", "subvolume", "snapshot", "/", ¤t_snapshot], "Saving current snapshot"); |
| 206 | +} |
| 207 | + |
| 208 | +pub fn handle_back() { |
| 209 | + println!("{}", "Rolling back to previous snapshot...".cyan().bold()); |
| 210 | + let snapshot_dir = "/var/cache/hacker/"; |
| 211 | + // Find latest current- snapshot |
| 212 | + let mut snapshots: Vec<_> = fs::read_dir(snapshot_dir).unwrap() |
| 213 | + .filter_map(|e| e.ok()) |
| 214 | + .filter(|e| e.file_name().to_string_lossy().starts_with("current-")) |
| 215 | + .collect(); |
| 216 | + snapshots.sort_by_key(|e| e.metadata().unwrap().modified().unwrap()); |
| 217 | + if let Some(latest) = snapshots.last() { |
| 218 | + let path = latest.path().to_string_lossy().to_string(); |
| 219 | + run_command_with_progress("sudo", vec!["btrfs", "subvolume", "set-default", &path], "Setting previous snapshot as default"); |
| 220 | + println!("{}", "Rolled back. Reboot to apply.".green().bold()); |
| 221 | + } else { |
| 222 | + println!("{}", "No previous snapshot found.".red().bold()); |
| 223 | + } |
| 224 | +} |
| 225 | + |
| 226 | +pub fn handle_clean() { |
| 227 | + println!("{}", "Cleaning old snapshots...".cyan().bold()); |
| 228 | + let snapshot_dir = "/var/cache/hacker/"; |
| 229 | + let fifteen_days_ago = Utc::now() - ChronoDuration::days(15); |
| 230 | + for entry in fs::read_dir(snapshot_dir).unwrap() { |
| 231 | + if let Ok(entry) = entry { |
| 232 | + let path = entry.path(); |
| 233 | + if let Ok(metadata) = entry.metadata() { |
| 234 | + if let Ok(modified) = metadata.modified() { |
| 235 | + let datetime: DateTime<Utc> = modified.into(); |
| 236 | + if datetime < fifteen_days_ago { |
| 237 | + run_command_with_progress("sudo", vec!["btrfs", "subvolume", "delete", path.to_str().unwrap()], "Deleting old snapshot"); |
| 238 | + } |
| 239 | + } |
| 240 | + } |
| 241 | + } |
| 242 | + } |
| 243 | + println!("{}", "Old snapshots cleaned.".green().bold()); |
| 244 | +} |
| 245 | + |
| 246 | +pub fn handle_snapshot() { |
| 247 | + println!("{}", "Creating system snapshot...".cyan().bold()); |
| 248 | + let snapshot_dir = "/var/cache/hacker/"; |
| 249 | + fs::create_dir_all(snapshot_dir).expect("Failed to create snapshot dir"); |
| 250 | + let timestamp = Utc::now().format("%Y%m%d%H%M%S").to_string(); |
| 251 | + let new_snapshot = format!("{}/manual-snapshot-{}", snapshot_dir, timestamp); |
| 252 | + run_command_with_progress("sudo", vec!["btrfs", "subvolume", "snapshot", "/", &new_snapshot], "Creating snapshot"); |
| 253 | + println!("{}", "Snapshot created.".green().bold()); |
| 254 | +} |
0 commit comments