|
| 1 | +require "option_parser" |
| 2 | +require "process" |
| 3 | +require "file_utils" |
| 4 | +require "colorize" |
1 | 5 |
|
| 6 | +# ANSI color codes |
| 7 | +RED = "\e[31m" |
| 8 | +GREEN = "\e[32m" |
| 9 | +BLUE = "\e[34m" |
| 10 | +RESET = "\e[0m" |
| 11 | + |
| 12 | +# Paths |
| 13 | +HACKEROS_UPDATE_SCRIPT = "/usr/share/HackerOS/Scripts/Bin/update-hackeros.sh" |
| 14 | +WALLPAPERS_UPDATE_SCRIPT = "/usr/share/HackerOS/Scripts/Bin/update-wallpapers.sh" |
| 15 | +BIN_PATH = "#{ENV["HOME"]}/.hackeros/hacker/HackerOS-Updates/HackerOS-Updater" |
| 16 | +AUTO_SCRIPT_PATH = "#{ENV["HOME"]}/.hackeros/auto-update.sh" # Script to wait for internet |
| 17 | + |
| 18 | +def display_header(title : String) |
| 19 | + puts "<--------[ #{title} ]-------->".colorize(:yellow) |
| 20 | +end |
| 21 | + |
| 22 | +def run_command(cmd : String) : {Bool, String} |
| 23 | + output = IO::Memory.new |
| 24 | + status = Process.run(cmd, shell: true, output: output, error: output) |
| 25 | + {status.success?, output.to_s} |
| 26 | +end |
| 27 | + |
| 28 | +def get_status(success : Bool) : String |
| 29 | + if success |
| 30 | + "#{BLUE}COMPLETE#{RESET}" |
| 31 | + else |
| 32 | + "#{RED}FAILED#{RESET}" |
| 33 | + end |
| 34 | +end |
| 35 | + |
| 36 | +def perform_updates : {String, String, String, String} |
| 37 | + # APT Update |
| 38 | + display_header("System Update") |
| 39 | + apt_success = true |
| 40 | + ["sudo apt update", "sudo apt upgrade -y", "sudo apt autoclean"].each do |cmd| |
| 41 | + success, _ = run_command(cmd) |
| 42 | + apt_success &&= success |
| 43 | + end |
| 44 | + apt_status = get_status(apt_success) |
| 45 | + |
| 46 | + # Flatpak Update |
| 47 | + display_header("Flatpak Update") |
| 48 | + flatpak_success, _ = run_command("flatpak update -y") |
| 49 | + flatpak_status = get_status(flatpak_success) |
| 50 | + |
| 51 | + # Snap Update |
| 52 | + display_header("Snap Update") |
| 53 | + snap_success, _ = run_command("sudo snap refresh") |
| 54 | + snap_status = get_status(snap_success) |
| 55 | + |
| 56 | + # Firmware Update |
| 57 | + display_header("Firmware Update") |
| 58 | + fw_success, _ = run_command("sudo fwupdmgr update") |
| 59 | + fw_status = get_status(fw_success) |
| 60 | + |
| 61 | + # HackerOS Update |
| 62 | + display_header("HackerOS Update") |
| 63 | + run_command(HACKEROS_UPDATE_SCRIPT) |
| 64 | + |
| 65 | + # Wallpapers Update |
| 66 | + display_header("Wallpaper Updates") |
| 67 | + run_command(WALLPAPERS_UPDATE_SCRIPT) |
| 68 | + |
| 69 | + {apt_status, flatpak_status, snap_status, fw_status} |
| 70 | +end |
| 71 | + |
| 72 | +def show_summary(apt_status, flatpak_status, snap_status, fw_status) |
| 73 | + puts "\nSystem Updates - #{apt_status}" |
| 74 | + puts "Flatpak Updates - #{flatpak_status}" |
| 75 | + puts "Snap Updates - #{snap_status}" |
| 76 | + puts "Firmware Updates - #{fw_status}" |
| 77 | +end |
| 78 | + |
| 79 | +def enable_automatic_updates |
| 80 | + # Create a script that waits for internet and runs the updater |
| 81 | + auto_script = <<-SCRIPT |
| 82 | + #!/bin/bash |
| 83 | + while ! ping -c 1 google.com &> /dev/null; do |
| 84 | + sleep 5 |
| 85 | + done |
| 86 | + #{BIN_PATH} |
| 87 | + SCRIPT |
| 88 | + |
| 89 | + File.write(AUTO_SCRIPT_PATH, auto_script) |
| 90 | + FileUtils.chmod(AUTO_SCRIPT_PATH, 0o755) |
| 91 | + |
| 92 | + # Add to crontab |
| 93 | + current_crontab = `crontab -l` |
| 94 | + unless current_crontab.includes?("@reboot #{AUTO_SCRIPT_PATH}") |
| 95 | + new_crontab = current_crontab + "\n@reboot #{AUTO_SCRIPT_PATH}\n" |
| 96 | + File.write("/tmp/crontab.txt", new_crontab) |
| 97 | + run_command("crontab /tmp/crontab.txt") |
| 98 | + File.delete("/tmp/crontab.txt") |
| 99 | + end |
| 100 | + |
| 101 | + puts "#{GREEN}Automatic updates enabled.#{RESET}" |
| 102 | +end |
| 103 | + |
| 104 | +def disable_automatic_updates |
| 105 | + # Remove from crontab |
| 106 | + current_crontab = `crontab -l` |
| 107 | + new_crontab = current_crontab.lines.reject { |line| line.includes?("@reboot #{AUTO_SCRIPT_PATH}") }.join("\n") |
| 108 | + File.write("/tmp/crontab.txt", new_crontab) |
| 109 | + run_command("crontab /tmp/crontab.txt") |
| 110 | + File.delete("/tmp/crontab.txt") |
| 111 | + |
| 112 | + # Remove script if exists |
| 113 | + File.delete(AUTO_SCRIPT_PATH) if File.exists?(AUTO_SCRIPT_PATH) |
| 114 | + |
| 115 | + puts "#{GREEN}Automatic updates disabled.#{RESET}" |
| 116 | +end |
| 117 | + |
| 118 | +def show_gui_menu |
| 119 | + loop do |
| 120 | + puts "\n[Q]uit - Close this terminal" |
| 121 | + puts "[R]eboot - Reboot the system" |
| 122 | + puts "[S]hutdown - Shutdown the system" |
| 123 | + puts "[L]og out - Log out from current session" |
| 124 | + puts "[T]erminal - Open a new Alacritty terminal" |
| 125 | + puts "[A]utomatic Updates - Enable automatic updates on boot" |
| 126 | + |
| 127 | + print "Enter your choice: " |
| 128 | + choice = gets.try(&.chomp.upcase) |
| 129 | + |
| 130 | + case choice |
| 131 | + when "Q" |
| 132 | + exit(0) |
| 133 | + when "R" |
| 134 | + run_command("sudo reboot") |
| 135 | + when "S" |
| 136 | + run_command("sudo shutdown -h now") |
| 137 | + when "L" |
| 138 | + # Assuming a desktop environment like GNOME or KDE; adjust if needed |
| 139 | + run_command("gnome-session-quit --logout --no-prompt") # or qdbus org.kde.ksmserver /KSMServer logout 0 0 0 for KDE |
| 140 | + when "T" |
| 141 | + Process.new("alacritty", input: Process::Redirect::Close, output: Process::Redirect::Close, error: Process::Redirect::Close) |
| 142 | + when "A" |
| 143 | + enable_automatic_updates |
| 144 | + else |
| 145 | + puts "#{RED}Invalid choice. Try again.#{RESET}" |
| 146 | + end |
| 147 | + end |
| 148 | +end |
| 149 | + |
| 150 | +def main |
| 151 | + with_gui = false |
| 152 | + gui_mode = false |
| 153 | + disable_auto = false |
| 154 | + auto_mode = false |
| 155 | + |
| 156 | + OptionParser.parse do |parser| |
| 157 | + parser.banner = "Usage: HackerOS-Updater [options]" |
| 158 | + parser.on("with-gui", "Run in GUI mode with Alacritty") { with_gui = true } |
| 159 | + parser.on("--gui-mode", "Internal GUI mode") { gui_mode = true } |
| 160 | + parser.on("disable-automatic-update", "Disable automatic updates") { disable_auto = true } |
| 161 | + parser.on("--auto", "Run in automatic mode (internal)") { auto_mode = true } |
| 162 | + end |
| 163 | + |
| 164 | + if disable_auto |
| 165 | + disable_automatic_updates |
| 166 | + return |
| 167 | + end |
| 168 | + |
| 169 | + if with_gui |
| 170 | + # Launch in Alacritty with gui-mode |
| 171 | + Process.new("alacritty", args: ["-e", BIN_PATH, "--gui-mode"], input: Process::Redirect::Close, output: Process::Redirect::Close, error: Process::Redirect::Close) |
| 172 | + return |
| 173 | + end |
| 174 | + |
| 175 | + apt_status, flatpak_status, snap_status, fw_status = perform_updates |
| 176 | + show_summary(apt_status, flatpak_status, snap_status, fw_status) |
| 177 | + |
| 178 | + if gui_mode |
| 179 | + show_gui_menu |
| 180 | + end |
| 181 | +end |
| 182 | + |
| 183 | +main if __FILE__ == Process.executable_path |
0 commit comments