mod config; mod diagnose; mod launcher; mod proton; mod service; mod tray; use anyhow::Result; use clap::{Parser, Subcommand}; use std::path::PathBuf; /// Battle.net launcher manager for Linux via umu/Proton-GE. /// /// Running without a subcommand starts the system tray daemon. /// Use `launch` in your .desktop shortcut for a direct, no-UI launch. #[derive(Parser)] #[command(name = "umutray", version, about)] struct Cli { #[command(subcommand)] command: Option, } #[derive(Subcommand)] enum Commands { /// Start the system tray daemon (default when no subcommand given) Tray, /// Launch Battle.net immediately and return — use this in .desktop shortcuts Launch, /// Gracefully kill all Battle.net / Wine processes Kill, /// Check setup health and report any problems Diagnose, /// Download and switch GE-Proton versions UpdateProton { /// Install the latest release automatically #[arg(long)] latest: bool, /// Install a specific version (e.g. GE-Proton9-20) #[arg(long, value_name = "VERSION")] version: Option, /// List recent releases and exit #[arg(long)] list: bool, }, /// Show or modify configuration Config { #[command(subcommand)] action: ConfigAction, }, /// Manage the systemd --user service that autostarts the tray Service { #[command(subcommand)] action: ServiceAction, }, } #[derive(Subcommand)] enum ConfigAction { /// Print the config file path and current values Show, /// Print just the config file path Path, /// Open the config file in $EDITOR Edit, /// Update one or more fields non-interactively Set { /// Wine prefix directory #[arg(long, value_name = "PATH")] prefix: Option, /// GE-Proton install directory #[arg(long, value_name = "PATH")] compat_dir: Option, /// umu GAMEID (used for protonfixes lookup) #[arg(long, value_name = "ID")] gameid: Option, }, } #[derive(Subcommand)] enum ServiceAction { /// Write the unit, daemon-reload, and enable+start the service Install, /// Stop, disable, and remove the unit file Uninstall, /// Show `systemctl --user status` for the service Status, } fn main() -> Result<()> { let cli = Cli::parse(); let config = config::Config::load()?; match cli.command.unwrap_or(Commands::Tray) { Commands::Tray => tray::run(&config)?, Commands::Launch => launcher::launch(&config)?, Commands::Kill => launcher::kill()?, Commands::Diagnose => diagnose::run(&config), Commands::UpdateProton { latest, version, list } => { proton::run(&config, latest, version, list)?; } Commands::Config { action } => match action { ConfigAction::Show => config.show()?, ConfigAction::Path => { println!("{}", config::Config::config_path()?.display()); } ConfigAction::Edit => config::Config::edit()?, ConfigAction::Set { prefix, compat_dir, gameid } => { let mut c = config; c.set_fields(prefix, compat_dir, gameid)?; } }, Commands::Service { action } => match action { ServiceAction::Install => service::install()?, ServiceAction::Uninstall => service::uninstall()?, ServiceAction::Status => service::status()?, }, } Ok(()) }